Как включить поля ввода из пользовательских директив в угловые формы?
Мне нужно создать простую форму с такими проверками - https://jsfiddle.net/rohansh20/k7omkz7p/2/
<div ng-app="module1" ng-controller="ctrl1 as vm">
<form novalidate name="vm.form1" class="css-form">
<label>Name:
<input type="text" name="Name" ng-model="vm.user.name" required />
</label>
<br />
<label>E-mail:
<input type="email" name="Email" ng-model="vm.user.email" required />
</label>
<br />
<input type="submit" ng-click="vm.save(vm.form1, vm.user)" value="Save" />
</form>
<div>
{{vm.result}}
</div>
<pre>form = {{vm.form1 | json}}</pre>
</div>
angular.module('module1', []);
angular.module('module1').controller('ctrl1', function() {
this.save = function(form, user) {
if(form.$invalid) {
this.result = 'Please correct the data entered';
return;
}
this.result = 'User ' + user.name + ' with email ' + user.email + ' saved successfully';
};
});
Но мне нужно динамически генерировать поля ввода. Поэтому я сделал директиву, которая преобразуется в поле ввода любого типа - https://jsfiddle.net/rohansh20/hdxj0np6/3/
<div ng-app="module1" ng-controller="ctrl1 as vm">
<form novalidate name="vm.form1" class="css-form">
<custom-input name="Name" type="text" model="vm.user.name" required="true">
</custom-input>
<br />
<custom-input name="Email" type="email" model="vm.user.email" required="true">
</custom-input>
<br />
<input type="submit" ng-click="vm.save(vm.form1, vm.user)" value="Save" />
</form>
<div>
{{vm.result}}
</div>
<pre>form = {{vm.form1 | json}}</pre>
</div>
var app = angular.module('module1', []);
app.controller('ctrl1', function() {
this.save = function(form, user) {
if(form.$invalid) {
this.result = 'Please correct the data entered';
return;
}
this.result = 'User ' + user.name + ' with email ' + user.email + ' saved successfully';
};
});
app.directive('customInput', function($compile) {
return {
restrict: 'E',
link: function(scope, element, attributes) {
var labelElement = angular.element('<label/>'),
name = attributes.name,
type = attributes.type,
ngModelString = attributes.model,
required = attributes.required,
inputElement = angular.element('<input/>');
inputElement.attr('ng-model', ngModelString);
inputElement.attr('name', name);
inputElement.attr('type', type);
if (required) {
inputElement.attr('required', 'required');
}
labelElement.append(name + ': ');
labelElement.append(inputElement);
$compile(labelElement)(scope);
element.replaceWith(labelElement);
}
}
});
Скрипки - это упрощенные версии того, что я пытаюсь сделать. Проблема заключается в том, что эти поля, даже если они скомпилированы и отрисованы идеально (что можно увидеть, изучив HTML), не включаются в состав родительского элемента управления формы. Это можно увидеть в отображаемом объекте управления формы в обеих скрипках. Из-за этого срок действия формы не может быть определен, и обе формы ведут себя по-разному при отправке неверного ввода.
Мне нужен элемент управления формы во второй скрипте, чтобы иметь правильные значения для его свойств и иметь дочерние элементы управления и их свойства, как в первой скрипте. Возможно ли это даже с помощью специальной директивы? Что мне нужно изменить, чтобы сделать эту работу?
Примечание. Директива будет включать сложные операции для динамического создания HTML, поэтому это должно быть сделано в функции ссылки директивы. Шаблон директивы с несколькими ngIfs просто не будет работать.
1 ответ
Чтобы не потерять привязки из родительской формы, включите ее в директиву пользовательской формы
В вашей директиве
(function () {
'use strict';
angular
.module('myApp')
.directive('customInput', customInput)
customInput.$inject = ['$compile'];
/* @ngInject */
function customInput ($compile) {
var directive = {
templateUrl: 'app/custom-input.html',
restrict: 'E',
transclude: true,
require: "?^form",
compile: compile,
controller:CustomInputController,
controllerAs:'vm',
scope:{
inputType:'=',
inputValue:'='
}
};
return directive;
function CustomInputController($scope){
var vm = this;
}
function compile(element, attributes){
return {
pre: preLink,
post: postLink
}
}
function preLink (scope,element,attrs, form, transclude){
}
function postLink (scope,element,attrs, form, transclude){
scope.currentForm = form;
$compile(element.contents())(scope);
}
}
})();
В вашей директиве HTML шаблон
<input type="inputType" ng-model="inputValue">
Когда вы называете свою директиву
<br-input type="text"
input-value="vm.user.email"
inputname="name"
input-required ="true">
</br-input>