1
votes

I have object like this:

"data": [
    {
        "id": 1,
        "name": "Checklist",
        "detail": [
            {
                "label": "Filter OK?",
                "type": "text"
            },
            {
                "label": "Package OK?",
                "type": "boolean"
            }
        ],
        "created_at": "2021-04-15T20:31:04.000000Z",
        "updated_at": "2021-04-16T13:44:36.000000Z"
    },..]

table with listed objects -> this.list = dataList.data;

<el-table v-loading="listLoading" :data="list" size="mini" stripe fit highlight-current-row style="width: 100%">
  <el-table-column align="left" label="" width="150">
    <template slot-scope="{row}">
      <el-button-group>
        <el-button type="primary" size="mini" icon="el-icon-folder-opened" @click="handleUpdate(row)" />
        <el-button type="danger" size="mini" icon="el-icon-delete" @click="deleteData(row)" />
      </el-button-group>
    </template>
  </el-table-column>
<el-table-column min-width="200px" align="left" :label="$t('position.name')">
    <template slot-scope="scope">
      <span>{{ scope.row.name }}</span>
    </template>
  </el-table-column>
</el-table>

then I just click for open one row - handleUpdate(row)

handleUpdate(row) {
  this.temp = Object.assign({}, row);
  this.dialogFormVisible = true;
  this.dialogStatus = 'update';
  this.$nextTick(() => {
    this.$refs['dataForm'].clearValidate();
  });
},

then a dialog appears

<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
  <el-form ref="dataForm" :rules="rules" :model="temp" label-position="right" label-width="90px" style="width: 400px; margin-left:50px;">
    <el-form-item :label="$t('position.name')" prop="name">
      <el-input v-model="temp.name" />
    </el-form-item>
    <el-divider />
    <el-form-item v-for="(item, index) in temp.detail" :key="index" prop="detail">
      <el-input v-model="item.name" />
    </el-form-item>
    <el-divider />
    <el-input v-model="checklistItem" placeholder="Nová položka" class="input-with-select">
      <el-button slot="append" icon="el-icon-plus" @click="addChecklistItem()" />
    </el-input>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogFormVisible = false">
      {{ $t('table.cancel') }}
    </el-button>
    <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
      {{ $t('table.save') }}
    </el-button>
  </div>
</el-dialog>

Then I change the name: "Checklist TEST" and also label of first item label: "Filter ok? TEST"

Then I just click on cancel btn and open the dialog for the same row again.

And here is the thing.. And I'm trying to figure out why is just field "name" reset after I close the popup without save. Changes what I type into detail array are kept.

Illustration: Init object fields:

"name": "Checklist",
    "detail": [
        {
            "label": "Filter OK?",
            "type": "text"
        },

Open first time and do the changes:

"name": "Checklist TEST",
    "detail": [
        {
            "label": "Filter OK? TEST",
            "type": "text"
        },

Close without save and open once again:

"name": "Checklist",
    "detail": [
        {
            "label": "Filter OK? TEST",
            "type": "text"
        },

Screenshots: enter image description here enter image description here

Name was reset but label not... I'm rly confused. What did I miss?

DEMO

Thanks for any help

1
Can you share some app screenshots of the process? Hard to visualize.Connor Low
Sure, screenshots addedghostix

1 Answers

1
votes

This is because Object.assign() only makes a shallow copy of the Object and you are modifying a nested property detail.name. You need to make a deeper copy like

this.temp = Object.assign({}, row, {
  detail: row.detail.map((item) => Object.assign({}, item)),
});

or using the spread operator

this.temp = {
  ...row,
  detail: [...row.detail.map(item => ({...item}))]
};

see this codesandbox

You can also use a helper like cloneDeep in lodash