Клацнувши прапорець клацанням ng, модель не оновлюється


85

Клацнувши прапорець і викликаючи ng-click: модель не оновлюється до натискання ng-click, тому значення прапорця неправильно представлене в інтерфейсі користувача:

Це працює в AngularJS 1.0.7 і, здається, не працює в Angualar 1.2-RCx.

<div ng-app="myApp" ng-controller="Ctrl">
<li  ng-repeat="todo in todos">
  <input type='checkbox' ng-click='onCompleteTodo(todo)' ng-model="todo.done">
    {{todo.text}}
</li> 
<hr>
task: {{todoText}}
<hr><h2>Wrong value</h2>
     done: {{doneAfterClick}}

і контролер:

angular.module('myApp', [])
  .controller('Ctrl', ['$scope', function($scope) {
    $scope.todos=[
        {'text': "get milk",
         'done': true
         },
        {'text': "get milk2",
         'done': false
         }
        ];


   $scope.onCompleteTodo = function(todo) {
    console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
    $scope.doneAfterClick=todo.done;
    $scope.todoText = todo.text;

   };
}]);

Broken Fiddle w / Angular 1.2 RCx - http://jsfiddle.net/supercobra/ekD3r/

Робоча скрипка з Angular 1.0.0 - http://jsfiddle.net/supercobra/8FQNw/


3
Також не працює для мене зараз, коли я оновив Angular до версії 1.2+
ac360

Також порушено у версії 1.2.24.
Вінсент П

Відповіді:


165

Як щодо зміни

<input type='checkbox' ng-click='onCompleteTodo(todo)' ng-model="todo.done">

до

<input type='checkbox' ng-change='onCompleteTodo(todo)' ng-model="todo.done">

З документів :

Обчислити заданий вираз, коли користувач змінює введення. Вираз не обчислюється, коли зміна значення надходить від моделі.

Зверніть увагу, що ця директива повинна ngModelбути присутнім.


3
здається, це також порушено у версії 1.2.7
JvdBerg

Свята лампочка, Бетмене! Я думав, що роблю щось інше зовсім неправильно, але це виявилося настільки просто, як це.
Адам Маршалл,

1
Дуже корисна відповідь! +1 Angular doc -1
neurix

що якщо вам потрібні дані події для запобіганняDefault?
user1943442


9

Порядок виконання ng-clickта ng-modelбуде виконуватися неоднозначно (оскільки жоден з них явно не встановлює їх priority). Найбільш стабільним рішенням цього було б уникнути використання їх на одному елементі.

Крім того, ви, мабуть, не хочете поведінки, яку показують приклади; Ви хочете checkboxвідповідати на клацання по всьому тексту мітки , а не лише на прапорці. Отже, найчистішим рішенням було б обернути inputng-model) всередині labelng-click):

<label ng-click="onCompleteTodo(todo)">
  <input type='checkbox' ng-model="todo.done">
  {{todo.text}}
</label>

Робочий приклад: http://jsfiddle.net/b3NLH/1/


Дуже дякую! Це єдине рішення, яке мені вдалося!
DaniCE

Це рішення все-таки найкраще!
Еллісан

8

Чому ви не використовуєте

$watch('todo',function(.....

Або іншим рішенням було б встановити todo.doneвнутрішній зворотний виклик ng-click і використовувати лише ng-click

<div ng-app="myApp" ng-controller="Ctrl">
<li  ng-repeat="todo in todos">
<input type='checkbox' ng-click='onCompleteTodo(todo)'>
    {{todo.text}} {{todo.done}}

і

$scope.onCompleteTodo = function(todo) {
        todo.done = !todo.done; //toggle value
        console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
        $scope.current = todo;
}

2
Дивіться відповідь @kakoni, я використовував ng-change замість ng-клацання, і час працює чудово. Це дозволяє зберегти двосторонній зв’язок і набагато чистіший підхід.
Майкл Мозер

6

Заміна ng-моделі на перевірену ng працює для мене.


Тільки те, що я хотів. Дякую!
Ісаак

Просто працював для мене з усіх доступних рішень тут.
thatzprem

2

Це свого роду хакерство, але загортання його в тайм-аут, здається, виконує те, що ви шукаєте:

angular.module('myApp', [])
    .controller('Ctrl', ['$scope', '$timeout', function ($scope, $timeout) {
    $scope.todos = [{
        'text': "get milk",
        'done': true
    }, {
        'text': "get milk2",
            'done': false
    }];

    $scope.onCompleteTodo = function (todo) {
        $timeout(function(){
            console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
            $scope.doneAfterClick = todo.done;
            $scope.todoText = todo.text;
        });
    };
}]);

1

Порядок між ng-modelі, ng-clickздається, різний, і це те, на що вам, мабуть, не слід покладатися. Натомість ви можете зробити щось подібне:

<div ng-app="myApp" ng-controller="Ctrl">
<li  ng-repeat="todo in todos">
<input type='checkbox' ng-model="todo.done" ng-click='onCompleteTodo(todo)'>
    {{todo.text}} {{todo.done}}
</li> 
    <hr>
        task: {{current.text}}
        <hr>
            <h2>Wrong value</h2>
         done: {{current.done}}
</div>

І ваш сценарій:

angular.module('myApp', [])
    .controller('Ctrl', ['$scope', function($scope) {

        $scope.todos=[
            {'text': "get milk",
             'done': true
             },
            {'text': "get milk2",
             'done': false
             }
            ];

        $scope.current = $scope.todos[0];


       $scope.onCompleteTodo = function(todo) {
            console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
    //$scope.doneAfterClick=todo.done;
    //$scope.todoText = todo.text;
       $scope.current = todo;

   };
}]);

Тут інакше, коли ви клацаєте поле, воно встановлює це поле як "поточне", а потім відображає ці значення у поданні. http://jsfiddle.net/QeR7y/


0

Зазвичай це пов'язано з іншою директивою між вашим ng-контролером та вашим введенням, яка створює нову область. Коли select виписує це значення, він запише його до останньої області, тому він буде писати його в цю область, а не в батьківську, що знаходиться далі.

Найкраща практика - ніколи не прив'язувати безпосередньо до змінної області дії в an ng-model, це також відомо, як завжди включаючи "крапку" у вашу ngmodel. Для кращого пояснення цього перегляньте це відео від Джона:

http://www.youtube.com/watch?v=DTx23w4z6Kc

Рішення з: https://groups.google.com/forum/#!topic/angular/7Nd_me5YrHU


Було б чудово, якби ви вказали маркер стрибка #t=5m08sу своєму посиланні на YouTube, тому не потрібно дивитися повне відео. Див. Mattcutts.com/blog/link-to-youtube-minute-second
Volker E.

0

Я просто замінив ng-modelна, ng-checkedі це спрацювало для мене.

Ця проблема виникла, коли я оновив свою кутову версію з 1.2.28до1.4.9

Також перевірте, чи ng-changeне спричиняє ваша проблема тут. Мені довелося видалити мою ng-changeкриницю, щоб вона запрацювала.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.