Solucionado (ver solução)
Solucionado
(ver solução)
12
respostas

Retorno de dados

Ola, eu preciso criar uma função que me retorne apenas os itens que estão checados na lista, como posso fazer isso com o map?

12 respostas

Oi Maria, tudo bem? Se é uma lista de itens que você pode marcar ou desmarcar, o mais recomendado é usar o filter que funciona de forma parecida com o map, mas com uma proposta diferente. Digamos que em um Array de números, eu queria apenas os maiores que 5. O filter seria feito da seguinte forma:

const numeros = [1,2,3,4,5,6,7,8,9,10]
const maioresQue5 = numeros.filter(numero => numero > 5);

O filter recebe um callback que deve retornar um valor verdadeiro ou falso, neste caso uso a comparação direta numero > 5. Pegou a ideia?

Peguei mais ou menos, eu fiz assim :

    state.todos.filter(e => {
        if(e.done == true){

            todoItems = Array.prototype.filter.call(state.todos, renderTodoItem).join('');

        }
    })

O todoItems ele retorna todos os itens da lista, nesse caso que mandei de exemplo, quero que retorne somente o que ele filtrou por true, como posso fazer?

Oi Maria, estou um pouco por fora do React em si, mas posso tentar te ajudar. Bom, pelo que vejo, a propriedade todos é a que tem todos os itens? Caso sim, o done é atualizado pelo próprio componente Todo, certo? Então pode ser feito apenas isso:

state.todos.filter(e => e.done)

como o done já é um booleano ao meu ver, você só precisa retornar o valor dele no filter. Então como o filter sempre retorna um novo array, você pode guardar em outra variável ou usar um setState direto no resultado.

const todosdone = state.todos.filter(e => e.done);

ou

this.setState({todos: state.todos.filter(e => e.done)})

Na realidade meu código está em JS puro, e agora preciso substituir o HTML para que quando clique em um botão aparece somente os filtrados, quando fiz o filtro acima, beleza, ele me retorna todos os que estão checados, mas não substituir no HTML, ele aparece apenas:

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

Para listar todos ele faz:

    var todoItems = [];
    if(state.todos){
        todoItems = Array.prototype.map.call(state.todos, renderTodoItem).join('');
    }

chama a funcao renderTodoItem para retornar o HTML, para retornar os específicos está:

todoItems = state.todos.filter(e => e.done, renderTodoItem);

porém ele retorna aqueles objetos apenas

Ahhhh, é que eu vi esse tal da state no meio do código e já achei que era React, desculpa! Me mostra então como funcionar essa renderização no HTML?

Ele funciona assim:

export function render(el, state) {
    var todoItems = [];
    if(state.todos){
        todoItems = Array.prototype.map.call(state.todos, renderTodoItem).join('');
    }

    todoItems = state.todos.filter(e => e.done, renderTodoItem);
    console.log(todoItems);

    el.innerHTML = renderApp(
        renderTodos(todoItems)
    );
}
function renderTodoItem(todo) {

    const todoClass = `todo__item todo__item--${todo.done ? 'done' : 'open'}`;
    return `<li class="${todoClass} list-group-item">
        <input class="js_toggle_todo" type="checkbox" data-id="${todo.id}"${todo.done ? ' checked' : ''}>
        ${todo.text}
    </li>`;
}
function renderTodos(todoItems) {

    return `<ul class="list-group">${todoItems}</ul>`;
}

Depois que eu fiz o filtro eu só preciso colocar os dados filtrados no HTML, por isso que quando uso a função filter, estou sobrescrevendo a variavel todoItems.

Neste caso a estratégia vai ter que ser outra pela lógica que eu entendi que você fez. Tenta o seguinte:

todoItems = Array.prototype.map.call(state.todos.filter(e => e.done), renderTodoItem).join('');

para o código ficar mais claro, você pode filtrar antes de mandar renderizar.

const todosdone = state.todos.filter(e => e.done);
todoItems = Array.prototype.map.call(todosdone, renderTodoItem).join('');

Legal funcionou, tens alguma dica para ele executar isso apenas quando for clicado no botão? Que está na função de HTML

solução!

Cria uma função separada, busca o elemento na página com o querySelector e usa a função addEventListener. Algo assim:

<button id="filtra">filtra</button>
<script>
const botaofiltrar = document.querySelector('#filtrar');
botaofiltrar.addEventListener('click', filtrarTodos);

function filtrarTodos(){
    const todosdone = state.todos.filter(e => e.done);
    todoItems = Array.prototype.map.call(todosdone, renderTodoItem).join('');
}
</script>

algo nessa linha :)

Eu criei a função dentro do render, porém não consigo chamar ela dentro do renderAddTodoAtTop como posso fazer?

Maria, tenta criar um novo tópico pra isso? Já estamos resolvendo dois problemas em um tópico só. O ideal é que quando um problema for resolvido, você abra um novo para o problema específico. Pode ser?

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software