Search code examples
vue.jsradio-buttonv-for

How to ++ radio buttons with v-for in VueJS on the fly


friends, I have a form that can be duplicated as many times I want, as showing above (just a small part, don´t really need all row):

<div class="col-sm-2">
    <div class="form-group">
        <label for="produtividade">Produtividade p/ha</label>

        <input
            type="text"
            class="form-control"
            name="previsaoReceitas[][produtividade]"
            v-model="previsaoReceita.produtividade"
            class="form-group"
            @keydown="$event.keyCode === 13 ? $event.preventDefault() : false"
        >
    </div>

    <div class="form-check form-check-inline">
        <input
            class="form-check-input"
            type="radio"
            name="previsaoReceitas[][embalagem]"
            v-model="previsaoReceita.embalagem"
            value="sc"
        >

        <label class="form-check-label" for="produtividade1">sc</label>
    </div>

    <div class="form-check form-check-inline">
        <input
            class="form-check-input"
            type="radio"
            name="previsaoReceitas[][embalagem]"
            v-model="previsaoReceita.embalagem"
            value="cx"
        >

        <label class="form-check-label" for="produtividade2">cx</label>
    </div>

    <div class="form-check form-check-inline">
        <input
            class="form-check-input"
            type="radio" name="previsaoReceitas[][embalagem]"
            v-model="previsaoReceita.embalagem"
            value="ton"
        >

        <label class="form-check-label" for="produtividade3">ton</label>
    </div>
</div>

There is this "+" button that calls a method to duplicate this line, pushing to an array so I can get the v-for:

<div v-for="(previsaoReceita, index) in previsaoReceitas">

The problem is when the row is duplicated, the radio button gets the same name and then the new invalidates the old, of course.

How can I make Vue name the new radio buttons on the fly?

I hope I made myself clear. Thank´s in advance!

Dear @Rich, now I am getting a weird result, check this out:

On the Vue data section:

previsaoReceita: {
                anoSafra: '',
                cultura: '',
                areaCultivada: '',
                produtividade: '',
                embalagem: '',
                preco: '',
                embalagem2: '',
                valor_previsto: ''
            },

The Vue inspector shows that the arrays are correct:

The first Vue data array

The previsaoReceitas array with two objects

The return:

 if ($request->previsaoReceitas != '') {
            $j = json_encode($request->previsaoReceitas);
            $im = str_replace('},{', ',', $j);
            $i = str_replace('","anoSafra', '"}, {"anoSafra', $im);
            return $i;
            $previsaoReceitas = new Producao();
            $previsaoReceitas->consorciado_id = $consorciado->id;
            $previsaoReceitas->producaos = $i;
            $previsaoReceitas->save();
        }

On the browser:

[{"anoSafra":"2016","embalagem":"cx","embalagem2":"sc","cultura":"batata","embalagem":"ton","embalagem2":"sc","areaCultivada":"100","produtividade":"100","embalagem":"sc","preco":"0.25","embalagem2":"sc"}, {"anoSafra":"2017","cultura":"batata","areaCultivada":"420","produtividade":"550"}, {"anoSafra":"2018","cultura":"batata","areaCultivada":"500","produtividade":"550"}]

Have you noted that only the first array has 'embalagem' and 'embalagem2' values?

Why is that? What I am doing wrong? Thank´s in advance!


Solution

  • You need to add the index's into the v-model, id, and for in your template to make sure they're all unique:

    <div
        v-for="(previsaoReceita, index) in previsaoReceitas"
        class="form-check form-check-inline"
    >
        <input
            :id="`produtividade-1-${index}`"
            class="form-check-input"
            type="radio"
            :name="`previsaoReceitas[${index}][embalagem]`"
            v-model="previsaoReceita[index].embalagem"
            value="sc"
        >
    
        <label
            :for="`produtividade-1-${index}`"
            class="form-check-label"
        >sc</label>
    </div>
    

    Make sure your previsaoReceitas array is able to handle the index, I'm not sure what your data or add method look like, but it should be something like this:

    data() {
        return {
            previsaoReceitas: [
                {
                    embalagem: null
                }
            ]
        };
    },
    
    methods: {
        add() {
            this.previsaoReceitas.push({
                embalagem: null
            });
        }
    }