Какое-то время пилю некоторое приложение на Laravel. На этот раз, для разнообразия, решил попробовать прилагающийся по умолчанию фронт-энд. На Vue.js который.
Не могу сказать, что обрел уже просветление и стал гурой, понимание предмета пока еще несколько клиповое. Но в целом после привычного ангуляра диким зверем фреймворк не выглядит, получается достаточно стройно и понятно. Хотя какие-то вещи и могут казаться странными.
В процессе освоения и использования, набрёл на любопытный хак. Захотелось мне, значит, сделать множество полей с автодополнением, примерно так (упрощенно):
<ol>
<li v-if="people" v-for="(person, index) in people">
<autocomplete
url="/people/search_by_name"
anchor="name"
label="email"
:initValue="person.name"
:onInput="autocompleteNameChanged"
:onSelect="autocompleteGetData"></autocomplete>
<button type="button" v-on:click="removePerson($event, index)" class="btn btn-default"><span class="fa fa-times"></span></button>
</li>
</ol>
Это поле автодополнения, а справа у каждого экземпляра кнопка для удаления с простым обработчиком:
removePerson: function (event, index) {
event.preventDefault();
this.people.splice(index, 1);
},
Проблема в том, что по нажатии на удаление визуально удаляется не выбранный элемент, а последний. Вот так:
Под капотом-то всё правильно происходит, если сохранить форму — удаленным окажется именно выбранный элемент. Но визуально это совсем не очевидно.
Вообще, во Vue.js есть такой атрибут :key
. Судя по описанию — то что надо. Но вот незадача: если у person
еще нет уникального id
, потому что мы работаем с формой создания, ничего не выйдет. Если в :key
поместить просто index
, то есть, порядковый номер — результат будет такой же, как на гифке выше.
Побродив по форумам в попытках обнаружить решение, наткнулся на занятный совет. Изменение атрибута :key
заставит Vue перерендерить список. То есть можно задать автодополнениям одно какое-то значение (не забудьте проинициализировать):
<autocomplete
...
:key="update_component_key"
...
:onSelect="autocompleteGetData"></autocomplete>
И обновлять его каждый раз, когда массив people
изменился и нужно перерендерить поля:
removePerson: function (event, index) {
event.preventDefault();
this.people.splice(index, 1);
this.update_component_key ++;
}
Так — работает:
В следующий раз можно посмотреть, например, как работают сами поля автодополнений (на основе существующего компонента, не самописные).