2015-03-25 2 views
14

У меня есть двусторонняя привязка данных, которая не изменяет значение переменной, отправленной в директиву.AngularJS Директива Двухсторонняя привязка данных не работает при наблюдении булевых

Моя директива часы для триггера и дает фокус на ассоциатов элемент (на основе кода найден здесь SO):

app.directive('focusMe', function ($timeout) { 
    return { 
    scope: { 
     trigger: '=focusMe' 
    }, 
    link: function (scope, element, attrs) { 
     scope.$watch('trigger', function(value) { 
     console.log("directive value: " + value); 
     console.log("directive start: " + scope.trigger); 
     if (value === true) { 
      $timeout(function() { 
      element[0].focus(); 
      scope.trigger = false; 
      console.log("directive end: " + scope.trigger); 
      }); 
     } 
     }); 
    } 
    } 
}); 

В HTML я называю это следующим образом:

<input type="text" ng-model="item.value" focus-me="focusInput" /> 

Когда я запускаю его в первый раз, он работает - потому что переменная focusInput переключает свое значение. Но focusInput в области контроллеров (вне директивы) не возвращается к false, когда директива завершается.

Этот переход на false должен произойти, когда я позвоню scope.trigger = false, предполагая, что я понимаю, что должно произойти.

Отсутствует, что приведет к тому, что двусторонняя привязка не приведет к возврату значения переменной, переданной в директиву?

UPDATE 01:

Для размещения вопроса я удалил небольшой кусочек кода. HTML на самом деле выглядит следующим образом:

<input type="text" ng-model="item.value" focus-me="focusInput" ng-if="item.condition != 'matches' && item.condition != 'does not match'" /> 

Если input поля скрывает, а затем повторно показано (на основе ng-if) директива будет правильно дать фокус в первый раз focusInput изменения. После этого он перестанет работать, если процесс скрыть/показать не будет повторяться.

ответ

29

Проблема, с которой вы столкнулись, является общей проблемой при работе с примитивными значениями (boolean, int и т. Д.) В пределах областей.

Я настоятельно рекомендую прочитать статью Understanding Scopes. (короткий ответ: примитивы изменяются в изолированной области действия директивы и не ищут цепочку для родительской области, т. е. область вашего контроллера).

О том, как решить вашу ситуацию, я предлагаю использовать точечную нотацию и хранить ваш примитивный внутри объекта и связать этот объект вашей директивы:

scope: { 
    triggerObj: '=focusMe' 
}, 

И убедитесь, что ваши ссылки триггера в директиве теперь scope.triggerObj.trigger.

И в контроллере есть:

$scope.triggerObj = {}; 
$scope.triggerObj.trigger = true; //or false, what have you 

Имея объект будет убедиться, что два способа привязки будет работать. И прочитайте статью выше, когда у вас есть время :)

5

Директива создает область действия. когда вы передаете параметр в область, объект передается по ссылке и boolean (и number, string ...), переданный по значению.

Например:

function changeToFalse(bool) { 
    bool= false; 
    console.log(bool); // false 
} 


function changeObjToFalse(obj) { 
    obj.bool= false; 
    console.log(obj.bool); // false 
} 

var obj = {bool : true}; 

changeToFalse(obj.bool); 
console.log(obj.bool); // true 
changeObjToFalse(obj); 
console.log(obj.bool); // false 

Смотрите также и тот же вопрос - two way binding not working with ng-repeat.