VueJS - Many to Many

[Finalizado Pelo Aluno]

Rafael Lannes Criador 11/01/2020
Rafael Lannes

Tenho um modal em vuejs onde eu realizo o cadastro de pessoa, nesse cadastro tem algumas informações que são de n-n e para isso eu usei checkbox para realizar o insert. Até aí OK.

Só que estou tendo dificuldade em fazer o update desse cadastro, pois estou utiizando o mesmo modal para o update. A minha dúvida é qual a melhor forma de tratar essa situação? Sendo que toda vez que o usuário marcar ou desmarcar algum check, o mesmo terá que ser adicionado/removido da tabela pivot

Criador Rafael Lannes 13/01/2020
Rafael Lannes

Para exemplificar melhor o problema:

Na parte de cadastro eu tenho a seguinte estrutura em html

HTML:

______________________________________________________

<div class="col-sm-6" v-for="(value, key, index) in problemas" :key="index">

    <div class="form-group">

        <div class="custom-control custom-checkbox">

            <input class="custom-control-input" type="checkbox" :id="value.id" :value="value.id" v-model="form.checked_problemas" />

            <label :for="value.id" class="custom-control-label">{{value.descricao}}</label>

        </div>

   </div>

</div>

________________________________

 

e no script eu declarei uma array:

 

 checked_problemas: []

Para inserir, ela é populada da seguinte forma:

checked_problemas:[4,6,8]

Então eu consigo fazer o insert na tabela pivot

_____________________________

 

Agora para alterar que é o problema, pois quando carrego o modal para editar a variavel que deveria ser uma array fica:

    checked_problemas: undefined

e quando marco ou desmarco algum, todos os checks vinculados no v-model são marcados ou desmarcados pois o valor retornado é true ou false

 

Qual a melhor maneira de trazer esses dados preenchidos e depois realizar o update? Pois os campos que serem desmarcados vão precisar ser excluidos da tabela pivot

 

 

PS: desculpa a má formatação, não consegui entender como identa 

 

 

 

 

Manager Carlos Ferreira 13/01/2020
Carlos Ferreira

Olá, Rafael!
Tudo bem?

Nesse caso recomendo que no backend (API) você utilize o método sync, porque toda vez que receber os dados do formulário basta sincronizar com o banco de dados, e tudo ok; (https://laravel.com/docs/6.x/eloquent-relationships#updating-many-to-many-relationships)

Já no frontend deve usar o two-way-databind (acredito que aqui está ok, certo?)

Criador Rafael Lannes 13/01/2020
Rafael Lannes

Show, não sabia dessa dica do laravel. Vou dar uma olhada...

no front end estou tendo problema para popular a variavel checked, como eu faria isso?

 

Manager Carlos Ferreira 14/01/2020
Carlos Ferreira

Tem esse código no GitHub, para eu poder dá uma olhada e analisar onde você está errando?

Criador Rafael Lannes 15/01/2020
Rafael Lannes

Quando tento editar o registro, não estou conseguindo popular os checboxes como marcado. A minha API retorna o seguinte objeto:

[

  •  
    {
    • id1,
    • descricao"Aquisição de Matéria Prima",
    • created_at"2020-01-14 14:18:29",
    • updated_at"2020-01-14 14:18:29",
    • pivot
       
      {
      • artesao_id1,
      • problema_id1
      }
    },
  •  
    {
    • id2,
    • descricao"Embalagem",
    • created_at"2020-01-14 14:18:29",
    • updated_at"2020-01-14 14:18:29",
    • pivot
       
      {
      • artesao_id1,
      • problema_id2
      }
    }

]

 

Criador Rafael Lannes 15/01/2020
Rafael Lannes

No HTML eu uso o mesmo modal para inserção/edição e está da seguinte forma:

<div class="col-sm-6" v-for="(valuekeyindexin problemas" :key="index">
                          <div class="form-group">
                            <div class="custom-control custom-checkbox">
                              <input
                                class="custom-control-input"
                                type="checkbox"
                                :id="value.id"
                                :value="value.id"
                                v-model="form.checked_problemas"
                              />
                              <label
                                :for="value.id"
                                class="custom-control-label"
                              >{{value.descricao}}</label>
                            </div>

Como eu consigo trazer esses valores marcados de acordo com o resultado da api?

Manager Carlos Ferreira 15/01/2020
Carlos Ferreira

É possível fazer o two-way-databind com os dados retornados da API.

Outra alternativa (talvez seja mais simples) é criar um método (ou propriedade computada) que retorna true ou fase, exemplo:

// Checkbox
<input
    class="custom-control-input"
    type="checkbox"
    :id="value.id"
    :value="value.id"
    v-model="form.checked_problemas"
    :checked="hasSelected(value.id)"
    :/>

// Método
hasSelected (id) {
    const problemasAtuais = this.problemas
    const problema = problemasAtuais.find(problema => problema.id == id);

    // retorna true caso exista, caso contrário retorna false
    return problema !== undefined;
}

Faça ao teste, fiz apenas de cabeça.

Criador Rafael Lannes 17/01/2020
Rafael Lannes

Fiz dessa maneira no html:

  <div class="custom-control custom-checkbox">
                              <input
                                class="custom-control-input"
                                type="checkbox"
                                :id="value.id"
                                :value="value.id"
                                v-model="form.checked_problemas"
                                :checked="hasSelected(value.id)"
                              />
                              <label
                                :for="value.id"
                                class="custom-control-label"
                              >{{value.descricao}}</label>
                            </div>

e no computed:

   hasSelected(id) {
      const problemasAtuais = this.problemas;
      const problema = problemasAtuais.find(problema => problema.id == id);

      // retorna true caso exista, caso contrário retorna false
      return problema !== undefined;
    }

porém, está dando esse erro e não funciona:

vue.common.dev.js?4650:630 [Vue warn]: Error in render: "TypeError: _vm.hasSelected is not a function"

 

found in

 

---> <Artesoes> at resources/js/components/Artesoes.vue

       <Root>

Manager Carlos Ferreira 17/01/2020
Carlos Ferreira

Olá amigo!

Deixe o hasSelected como método, declare em mehtods: {...}

No aguardo.

Criador Rafael Lannes 20/01/2020
Rafael Lannes

Coloquei dessa maneira, e o erro parou de acontecer.

Porém, quando eu abro o modal para editar a variavel checked_problemas está como undefined, deveria vim uma array com os valores marcados, correto?

E quando eu marco algum check, ela muda o valor para true, marcando todos os grupos de checbox

Criador Rafael Lannes 20/01/2020
Rafael Lannes
hasSelectedProblemas(id) {
       //Essa variavél, não deveria receber os valores que foram marcados da tabela pivot? 
       //Pois o this.problemas é o objeto com todos os problemas 
      const problemasAtuais = this.problemas;
      const problema = problemasAtuais.find(problema => problema.id == id);

      // retorna true caso exista, caso contrário retorna false
      return problema !== undefined;
    },
Manager Carlos Ferreira 20/01/2020
Carlos Ferreira

Olá amigo!

A propriedade "problemasAtuais" deve conter apenas os problemas que foram vinculados (N:N);

Nesse component você precisa ter uma propriedade com apenas os valores selecionados, pois é baseado nesses valores que vamos validar para o checkbox vir marcado ou não.

Exemplo com JS puro (testado):
const problemas = [
    {id: 1, name: 'pro1'},
    {id: 2, name: 'pro2'},
    {id: 3, name: 'pro3'},
    {id: 4, name: 'pro4'},
    {id: 5, name: 'pro5'},
]

// Dados que foram inseridos antes (N:N)
const problemasAtuais = [
    {id: 1, name: 'pro1'},
    {id: 4, name: 'pro4'},
    {id: 3, name: 'pro4'},
]

function hasSelectedProblemas(id) {

  const problema = problemasAtuais.find(problema => problema.id == id);

  return problema !== undefined;
}

console.log(hasSelectedProblemas(1))

Criador Rafael Lannes 21/01/2020
Rafael Lannes

Beleza, professor. fiz as alterações e o problema continua devido ao v-model, acredito... nunca pensei que fosse dar tanta dificuldade rss

Mesmo fazendo essas alterações, o v-model fica como undefined, como eu consigo fazer com que ela receba um array? Pois quando inspeciono o elemento e coloco a array na mão, os valores na tela são preenchidos e só falta isso para completar o crud

  1.  
Criador Rafael Lannes 21/01/2020
Rafael Lannes
    1.  

0:

id: 1

descricao: "Aquisição de Matéria Prima"

created_at: "2020-01-14 14:18:29"

updated_at: "2020-01-14 14:18:29"

1:

id: 2

descricao: "Divulgação"

created_at: "2020-01-14 14:18:29"

updated_at: "2020-01-14 14:18:29"

quando eu adiciono a array na mão, o formulário é preenchido corretamente:

checked_problemas:Array[2]
 
 
 
 
0:1
 
 
 
 
 
1:2

 

Como eu consigo transformar esse objeto em uma array desse tipo? Acredito que resolvendo isso, acaba o problema

Criador Rafael Lannes 21/01/2020
Rafael Lannes
  1. (2) [{…}, {…}, __ob__: Observer]
    1. 0:
      1. id: 1
      2. descricao: "Aquisição de Matéria Prima"
      3. created_at: "2020-01-14 14:18:29"
      4. updated_at: "2020-01-14 14:18:29"
      5. 1
      6. id: 2
      7. descricao: "Divulgação"
      8. created_at: "2020-01-14 14:18:29"
      9. updated_at: "2020-01-14 14:18:29"


Criador Rafael Lannes 21/01/2020
Rafael Lannes

Na verdade nem sei mais, to perdido... eu fiz o seguinte teste

if (this.form.checked_problemas == undefined) {
        this.form.checked_problemas = [13];
        this.form.checked_problemas.push(65);
         console.log(this.form.checked_problemas'teste');
      }

Na teoria, deveria imprimir o array, certo? Só que o resultado é esse:

[__ob__: Observer]

length: 0

__ob__: Observer {value: Array(0), dep: Dep, vmCount: 0}

__proto__: Array

 

 

 

 

Manager Carlos Ferreira 21/01/2020
Carlos Ferreira

Você tem esse código no GitHub, para eu poder dá uma olhada e analisar onde você está errando?

Criador Rafael Lannes 22/01/2020
Rafael Lannes

https://bitbucket.org/rafaellannes/debug

A rota /register tá funcionando e eu coloquei o arquivo sql do banco pra poupar tempo.

O arquivo em questão é o Artesoes.vue. Na primeira aba tem os check's, infelizmente não consegui avançar mto. Eu estava realizando testes no método EditModal, pois ali tenho o objeto completo com todos os dados, mas testei várias soluções e não consegui avançar.

Obrigado pela ajuda

Criador Rafael Lannes 22/01/2020
Rafael Lannes

https://bitbucket.org/rafaellannes/debug/src/master/

(coloquei o link em cima tb, mas ficou invisivel devido a formatação)

Manager Carlos Ferreira 23/01/2020
Carlos Ferreira

Olá, Rafael!

Esse bug tá em qual component mesmo?

Sabe a Solução? Ajude a resolver!

Precisa estar logado para conseguir responder a este ticket!

Clique Aqui Para Entrar!