Угловая модель теряет область действия с включенным в директиву ng

Я не был уверен, как правильно назвать этот вопрос, так что вот оно..

Я пытаюсь настроить динамический способ изменения шаблонов внутри директивы, используя метод ng-include. Я создал два примера Plunker, и хотя один должен работать так же, как и другой, похоже, это не так.

HTML для обоих примеров:

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <main></main>
  </body>

</html>

Пример №1: http://plnkr.co/edit/bi3Plrm8xufuN79Nvajj?p=preview

Я устанавливаю две директивы (одну основную и одну вложенную как дочернюю):

angular.module('myApp', ['Test']);
angular.module('Test', [])
.directive('main', [
    function () {
        return {
            restrict: 'E',
            template: '<input type="text" ng-model="myModel"><br><br><child></child>'
        };
    }
])
.directive('child', [
    function () {
        return {
            restrict: 'E',
            template: '<input type="text" ng-model="myModel">'
        };
    }
]);

Легкий. При запуске приложения оба поля заполняются соответственно по мере изменения модели.

Пример № 2: http://plnkr.co/edit/3ajcTyfJElEzbqvsWwBM?p=preview

HTML остается прежним, но js немного отличается:

angular.module('myApp', ['Test']);
angular.module('Test', [])
.directive('main', [
    function () {
        return {
            restrict: 'E',
            template: '<input type="text" ng-model="myModel"><br><br><child></child>'
        };
    }
])
.directive('child', [
    function () {
        return {
            restrict: 'E',
            controller: function($scope) {
              $scope.myTemplate = 'test-template.html'
            },
            template: "<div ng-include='myTemplate'></div>"
        };
    }
]);

тест-template.html:

<input type="text" ng-model="myModel">

На этот раз, если я взаимодействую с первым сгенерированным вводом, оба ввода обновляются соответственно, как и должны. Вот когда становится интересно... Когда/если я взаимодействую со вторым вводом (тот, который сгенерирован ng-include), я теряю все привязки. Навсегда... Как будто создал свою версию модели. После этого изменение первого входа не влияет на второй.

Что здесь происходит? Действительно ли он создает новый экземпляр myModel? И если да, то как этого можно избежать при использовании этого ng-include метода?


comment
ng-include создает дочернюю область. Измените его на ng-model="myModel.value" в обоих случаях и убедитесь, что он работает.jsbin.com/tehiranopi/3/edit   -  person PSL    schedule 30.10.2014
comment
stackoverflow.com/questions/14049480/   -  person PSL    schedule 30.10.2014
comment
stackoverflow.com/questions/15705532 /   -  person PSL    schedule 30.10.2014
comment
Спасибо, я совсем забыл про дочернюю область.   -  person spez86    schedule 30.10.2014


Ответы (1)


Это не странно, как сказал PSL, ng-include создает новую область.

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

<input type="text" ng-model="myModel">

To:

<input type="text" ng-model="$parent.myModel">

person Linial    schedule 30.10.2014
comment
Итак, если у вас есть еще 2 дочерних области, вы сделаете $parent.$parent.$parent.myModel? странно нет? - person PSL; 30.10.2014
comment
Да, это странно, но я не мог представить, что вы когда-нибудь захотите создать 3 вложенных дочерних области. что ты предлагаешь? - person Linial; 30.10.2014
comment
Считаете ли вы, что ваша HTML-структура всегда будет простой? Может быть множество примеров, что это не так. что, если вы ng-включаете содержимое внутри ng-repeat, которое, вероятно, находится внутри ng-if .. просто говорю .. :) Дело в том, что $parent - это худший способ решить проблему. - person PSL; 30.10.2014
comment
Определенно нет, но именно поэтому я спрашиваю вас, какое решение является наиболее подходящим для этого сценария? - person Linial; 30.10.2014
comment
См. ссылку, которую я прикрепил, и jsbin в комментариях к вопросу. - person PSL; 30.10.2014
comment
Хороший! будет ли это работать так же, если есть больше вложенных областей? - person Linial; 30.10.2014
comment
Давайте продолжим обсуждение в чате. - person Linial; 30.10.2014
comment
jsbin.com/roxecupila/1/edit, и этот ответ должен прояснить stackoverflow.com/questions/14049480/. Извините, я не могу использовать чат здесь :( - person PSL; 30.10.2014
comment
Есть ли случаи, когда вам нужно использовать $parent? Я имею в виду, что в моем коде ng-click вложен в ng-repeat, у меня там работает только $parent, это нормально? - person Linial; 30.10.2014
comment
Я никогда не сталкивался со случаем, когда у меня нет лучшей альтернативы, чем использовать parent. Вот ответ, на который я ответил несколько дней назад с другими альтернативами. stackoverflow.com/questions/26555720/ Вопрос заключался в том, как избавиться от $parent: D Проблема, почему я ненавижу использование parent, заключается в том, что тот, кто использует $parent, делает много предположений о том, каковы его внешние области. конструкции, которые могут вызвать проблемы с ремонтопригодностью. - person PSL; 30.10.2014
comment
Ничего себе, я только что изменил две строки кода в своем проекте, и он больше не использует $parent, однако мне пришлось объявить несколько строк в контроллере. без них я не мог бы ссылаться на тот же объект во вложенной области. поэтому я предполагаю, что $parent делает предположение, и определение объекта в контроллере создает возможность для изменения. АККУРАТНЫЙ. - person Linial; 30.10.2014
comment
Ага. И вы просто имеете дело со своей предопределенной моделью представления, так что ничего непредсказуемого, никаких $parent или чего-то еще .. :) Сегодня здесь был еще один вопрос stackoverflow.com/questions/26658679/, вы можете обойти с законным использованием ng-init. - person PSL; 30.10.2014