#javascript #angularjs
#javascript #angularjs
Вопрос:
У меня есть шаблон, который динамически создает входной элемент во время выполнения. Я хочу записать данные, введенные в этот входной элемент, в мою модель. Я пытаюсь добиться этого с помощью ng-model. Однако он не работает. При проверке элемента я вижу, что правильное выражение было привязано к ng-model, но оно не обновляет мою модель. Вот мой код:
Шаблон:
<div child-ng-model="userReg.candidateData.PrimarySkills">
<!-- this div creates an input element on runtime -->
</div>
Директива:
(function (window) {
'use strict';
angular.module('myApp.userRegistration.directive')
.directive('childNgModel', ['$compile', function ($compile) {
return {
restrict: 'A',
scope: {
childNgModel: '@'
},
link: function (scope, element, attrs) {
var el = element.children().eq(0);
el.attr('ng-model', scope.childNgModel);
$compile(el)(scope);
}
}
}]);
})(window);
Ниже вы можете увидеть, какое правильное значение присваивается ng-model:
Текст, который я ввожу в поле ввода, не фиксируется моей моделью (userReg.candidateData.PrimarySkills). Почему это происходит? Что я здесь делаю не так?
Ответ №1:
Проблема в том, что вы создаете изолированную область в своей директиве. Таким образом, ngModel не может выполнять запись во внешнюю переменную области видимости.
Попробуйте выполнить следующее:
(function (window) {
'use strict';
angular.module('myApp.userRegistration.directive')
.directive('childNgModel', ['$compile', function ($compile) {
return {
restrict: 'A',
scope: true, // create a normal child scope
link: function (scope, element, attrs) {
var el = element.children().eq(0);
el.attr('ng-model', attrs.childNgModel); // just get the attribute value
$compile(el)(scope);
}
}
}]);
})(window);
Комментарии:
1. Спасибо. Есть еще одна незначительная, не связанная с этим проблема 🙂 Когда я утешаю. зарегистрируйте мой объект candidateData, я не вижу всех свойств в окне инструмента Chrome dev. Некоторые свойства обрезаются символом «…» в конце. Даже после нажатия стрелки, которая расширяет объект, я не вижу всех свойств. Есть ли способ это исправить? Вот ссылка: s18.postimg.org/4bv9c1r7d/Untitled2.png
2. @dk49 Это делает директиву напрямую зависимой от контроллера и является плохой практикой. ( docs.angularjs.org/guide /… см. зеленую заметку над этим абзацем)
3. @gyc Зависимости нет. (Имя) модели передается директиве, поэтому директиву можно использовать с любым контроллером.
4. @gyc, zeroflagL прав. Имя «MyApp.UserRegistration.directive» — это, по сути, модуль, к которому я прикрепил свою директиву. Возможно, соглашение об именовании вас смутило. Мы в основном следуем очень модульному шаблону, в котором каждая директива / контроллер / сервер регистрируется в отдельном модуле. Чтобы определить иерархию, мы следуем соглашению об именовании ‘appModuleName.featureModuleName.directive / controller / service’. Этот шаблон позволяет многократно использовать директивы, контроллеры и службы по всему приложению в разных модулях.
5. Ваша директива имеет то же имя, что и переменная области видимости внутри директивы «childNgModel». Это плохая практика. Вы и zeroflagL можете следовать или не следовать хорошей практике. Это больше не мое дело. Спасибо. (у вас есть все необходимые ссылки и правильный ответ (zeroflagL или мои правильные))
Ответ №2:
Модель недоступна внутри директивы.
Сначала необходимо установить двустороннюю привязку:
scope: {
childNgModel: '='
Изменение модели ввода на childNgModel
:
el.attr('ng-model', "childNgModel");
$compile(el)(scope);
Теперь входные данные обновляются childNgModel
внутри директивы, которая сама связана с userReg.candidateData.PrimarySkills
внешней директивой.
Ответ №3:
Вы передаете модель в виде интерполированной строки, используя ‘@’.
Вместо этого попробуйте использовать ‘=’.
Если вы хотите, чтобы интерполированная строка содержалась в модели, вам нужно окружить ее {{ child-ng-model="userReg.candidateData.PrimarySkills" }}
Однако использование одного и того же имени для директивы и модели в директиве является плохой практикой. Вам лучше создать атрибут специально для модели.
function MyController() {
this.userReg = {candidateData: {PrimarySkills:["123", "456", "789"]}};
}
function childNgModel($compile) {
return {
restrict: 'A',
scope: {
value: '='
},
link: function (scope, element, attrs) {
console.log(scope.value);
}
}
}
angular.module('app', []);
angular.module('app')
.controller('MyController', MyController)
.directive('childNgModel', childNgModel);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MyController as ctrl">
<div child-ng-model value="ctrl.userReg.candidateData.PrimarySkills">
</div>
</div>
</div>
ИЛИ это
function MyController() {
this.userReg = {candidateData: {PrimarySkills:["123", "456", "789"]}};
}
function childNgModel($compile) {
return {
restrict: 'A',
scope: {
value: '@'
},
link: function (scope, element, attrs) {
console.log(scope.value);
}
}
}
angular.module('app', []);
angular.module('app')
.controller('MyController', MyController)
.directive('childNgModel', childNgModel);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MyController as ctrl">
<div child-ng-model value="{{ctrl.userReg.candidateData.PrimarySkills}}">
</div>
</div>
</div>
Комментарии:
1. «использование одного и того же имени для директивы и модели в директиве является плохой практикой» , так что, по вашему мнению
ng-model="foo"
, должно бытьng-model value="foo"
. Почему именно?2. Нет, ваша директива не должна иметь то же имя, что и атрибут, который вы привязываете к области видимости. Это сбивает с толку. Вы можете вызвать директиву «myDirective» и модель ng-model.
3. Директива вызывается
ngModel
, и мы не можем ее переименовать, потому что она встроенная. И вы говорите, что это плохой дизайн и сбивает с толку, но ни у кого никогда не было проблем с этим. Вы все еще не объяснили причину своего мнения.4. @zeroflagL О чем ты говоришь? Вы, кажется, очень смущены. childNgModel — это ЕГО директива и переменная области видимости, привязанная к ней одновременно. Это плохая практика. ng-model — это угловая директива, конечно, вы не можете ее изменить. Где вы видите ссылку на ng-model здесь??
5. Вы написали: «использование одного и того же имени для директивы и модели в директиве является плохой практикой» .
ngModel
делает именно это. Так что, по вашему мнению,ngModel
плохо спроектировано. И вы все еще не объяснили, почему это плохая практика.