2014-12-09 2 views
4

Обратите внимание, что это противоположность 99% связанных вопросов о stackoverflow.Angularjs обновляет вид, но не модель

Проблема Mi: у меня есть зависимый выбор, когда изменяется «Master», представление «Slave» обновляется, но не является его моделью. WEIRD.

Пример кода:

<!DOCTYPE html> 
<html ng-app> 

<head> 
    <script src="https://code.angularjs.org/1.3.5/angular.js"></script> 
</head> 

<body> 
    <select ng-model='master'> 
    <option value='m1'>Master 1</option> 
    <option value='m2'>Master 2</option> 
    </select> 
    <select ng-model='slave'> 
    <option value='Slave 1 selected' ng-selected='master == "m1"'>Slave 1</option> 
    <option value='Slave 2 selected' ng-selected='master == "m2"'>Slave 2</option> 
    </select> 
    {{ slave }} 
</body> 

</html> 

При изменении Мастер выбора, вы можете увидеть изменение выбора, но не напечатанное значение для связывания {{}} рабыня.

Ссылка на plunker: http://plnkr.co/edit/LjaKgTTfBlczkGuCIhZ1

+2

Моей догадки это происходит потому, что нг -selected вообще не знает о модели, он просто устанавливает выбранный атрибут и не вызывает никаких изменений значений, поэтому модель не обновляется. – Rytmis

+0

Почему вы не используете ng-options? ng-selected не обновляет ng-model – PSL

+0

Вы ищете что-то вроде этого? http://stackoverflow.com/questions/25413071/how-to-handle-cascading-chained-dropdowns-using-multiple-ng-options – PSL

ответ

1

Угловые Обновляет представление на основе типовых изменений и модели, основанные на пользовательских взаимодействий с точки зрения. Изменяя выбранный параметр вручную с помощью ng-selected, угловой не видел, чтобы пользователь выбирал новую опцию и, следовательно, не обновлял slave. А так как slave не изменился с тех пор, как последний задал выбранный параметр в элементе управления, он не обновит выбранную опцию. Я не думаю, что вы должны использовать ng-model и ng-selected вместе. Я думаю, что это имеет общий смысл и не является ошибкой в ​​угловом, ng-selected просто не предназначен для использования таким образом.Подумайте об этом коде:

$scope.buttonClicked = function() { 
    $scope.slave = "Slave 1 selected"; 
    $scope.master = "m2"; 
}; 

Что значение slave должно быть и какой вариант следует выбрать? Вы задали оба параметра в коде, что нужно сделать угловым для выбора html? Следует ли игнорировать настройку «ведомого» значения? Должен ли он игнорировать атрибут ng-selected, который говорит, что он должен выбрать ведомый 2, если master - m2? Предположим, вы установили master в m1, это вызывает ng-selected, чтобы сделать выбранное ведомое устройство 1. Что, если пользователь затем изменит параметр на ведомый 2? Опция ng-selected неверна.

Если вы хотите сделать установку одноразового значения подчиненного, когда мастер меняется, вы должны создать часы для запуска кода при изменении значения:

$scope.$watch('master', function(newValue, oldValue) { 
    if (newValue == 'm1') { 
    $scope.slave = 'Slave 1 selected'; 
    } else if (newValue == 'm2') { 
    $scope.slave = 'Slave 2 selected'; 
    } else { 
    $scope.slave = undefined; 
    } 
}); 
+0

Я принимаю это, потому что он ТОЛЬКО имеет правильный ответ, но @ new-dev также был прав: Правильный способ реализовать это, по сути, через $ watcher ' – Daniel

+0

И у него есть пример рабочего кода. +1 – Daniel

0

Угловой подход к этому должен были бы изменить рабскую модель напрямую, а не только DOM (ng-selected в основном только устанавливает атрибут selected, если оно истинно, ничего). Технически вы можете взломать это, добавив наблюдателя, который также будет обновлять модель, но переписывание это звучит как гораздо лучшая идея.

Вот пример, это немного коряво, но заменить был самым быстрым, что я мог сделать без фактического написания некоторых JS (но вы получите идею):

<select ng-model='master' ng-change="slave = master.replace('m', 's')"> 
    <option value='m1'>Master 1</option> 
    <option value='m2'>Master 2</option> 
    </select> 
    <select ng-model='slave'> 
    <option value='s1' >Slave 1</option> 
    <option value='s2' >Slave 2</option> 
    </select> 

http://plnkr.co/edit/WT7vb7yvtcvaUPUwGXdI?p=preview

+1

Я уверен, что исходный вопрос не так прост, как замена m и s ..: D – PSL

+0

Я тоже, но мы не знаем, что именно пытается сделать OP (почему две модели?), заменив мой способ избежать создания объекта mapper. :) – Shomz

+0

Просто используйте ng-options ... Это то, для чего это необходимо. – PSL

1

@ ответ Shomz в это один из способов, хотя replace кажется немного взломанным.

Причина, по которой slave не обновляется, заключается в том, что Angular осторожно относится к изменению ViewModel без знания разработчика. Как правило, ViewModel должен быть изменен либо контроллером в ответ на внешнее событие, либо с помощью действия «Вид - в ответ на действие пользователя». В этом случае изменение было бы в ответ на изменение свойства selected на подчиненном устройстве, поэтому Угловое значение не изменяется slave.

Еще один способ думать о нем: Как бы slave обновляться в ответ на изменение master, если вы не имеете представления (т.е. <select>), например, в случае с блок-тестирования контроллера.

Правильный способ реализовать это, по сути, через $watcher - поэтому я не согласен с этим пунктом с @Shomz.

Я также предложил бы оценить, почему вам нужны как ведущие, так и подчиненные, чтобы заслонять друг друга. Если это так, то вы должны использовать один и тот же ng-model:

<select ng-model="master2" 
     ng-options="val.k as val.v for val in [{k: 'm1', v: 'Master1'}, {k: 'm2', v: 'Master2'}]"> 
</select> 
<select ng-model="master2" 
     ng-options="val.k as val.v for val in [{k: 'm1', v: 'Slave 1'}, {k: 'm2', v: 'Slave 2'}]"> 
</select> 
+0

да. Я бы просто пошел с ng-вариантами. – PSL

+0

В части наблюдателя я имел в виду написать конкретный «scope. $ Watch» («master» ... «вещь, это было бы очень плохо». И я сказал, что замена была чистой лень. :) Дело в том, что выбран только ng заботится о DOM. – Shomz

+0

@Shomz, почему? Если 'slave' выполняет некоторую условную затенение' master', я бы сказал, что это _is_ путь. Если это всегда одно и то же, то это должно быть одно и то же свойство ViewModel –