Мне нужно динамически добавлять элементы в Angularjs.
Я успешно их добавил.
Но я не могу передать их значения в переменные области видимости.
Мне нужно создавать элементы на отдельной фабрике, а не создавать внутри директивы.
fieldsFactory добавить элементы для входных данных. Эти элементы должны предоставлять данные в массив data в директиве области действия wrapper.
Вы можете помочь?
angular.module('app', [])
.factory('fieldsFactory', fieldsFactory)
.directive('wrapper', wrapper);
function wrapper(fieldsFactory) {
return {
template: `
<div>
<button ng-click = "addField('select')">Add select</button>
<button ng-click = "addField('input')">Add input</button>
<pre ng-bind = "data"></pre>
</div>
`,
link: wrapperLinkFn
}
}
function wrapperLinkFn(
scope,
iElement,
iAttrs,
iCtrl,
transcludeFn
) {
scope.addField = addField;
scope.fieldsCounter = 0;
var fieldsFactory = iElement.injector().get('fieldsFactory');
function addField(fieldType) {
fieldsFactory(scope, iElement, fieldType, scope.fieldsCounter);
scope.fieldsCounter++;
}
}
function fieldsFactory() {
return function(scope, iElement, fieldType, fieldsCounter) {
var field;
switch (fieldType) {
case 'input':
field = `<div><input ng-model = "data[${fieldsCounter}]"><div>`;
break;
case 'select':
field = `
<div>
<select ng-model = "data[${fieldsCounter}]">
<option value = "select1">select1</option>
<option value = "select2">select2</option>
</select>
</div>
`;
break;
default:
field = '';
}
iElement.injector().invoke(function($compile) {
iElement.append($compile(field)(scope));
});
}
}
angular.bootstrap(
document.getElementById('root'), ['app']
);<script src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div id = "root">
<wrapper></wrapper>
</div>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Мои шаги:
определил isolateScope для созданных элементов
var isolateScope = iElement.scope().$new(true);
определенная переменная в isolateScope для хранения введенных данных
определенная функция ng-change, которая вызывает функцию в родительской области
isolateScope.onChange = function() {
iElement.scope().setFieldValue(fieldsCounter, isolateScope.fieldValue);
}
определил функцию в родительской области, которая устанавливает значение для определенного ключа и запускает цикл $digest для родительской области
function setFieldValue(key, value) {
scope.data[key] = value;
}
определил функцию, которая связывает значение данных
function getData() {
return scope.data;
}
angular.module('app', [])
.factory('fieldsFactory', fieldsFactory)
.directive('wrapper', wrapper);
function wrapper(fieldsFactory) {
return {
template: `
<div class = "container m-2">
<button
ng-click = "addField('select')"
class = "btn btn-outline-primary"
>Add select</button>
<button
ng-click = "addField('input')"
class = "btn btn-outline-primary"
>Add input</button>
<div class = "list-group mt-2 w-50">
<div
ng-repeat = "field in getData()"
ng-bind = "field"
class = "list-group-item"
></div>
</div>
</div>
`,
link: wrapperLinkFn
}
}
function wrapperLinkFn(
scope,
iElement
) {
scope.addField = addField;
scope.setFieldValue = setFieldValue;
scope.getData = getData;
scope.fieldsCounter = 0;
scope.data = {};
function setFieldValue(key, value) {
scope.data[key] = value;
}
function getData() {
return scope.data;
}
var fieldsFactory = iElement.injector().get('fieldsFactory');
function addField(fieldType) {
fieldsFactory(scope, iElement, fieldType, scope.fieldsCounter);
scope.fieldsCounter++;
}
}
function fieldsFactory() {
return function(scope, iElement, fieldType, fieldsCounter) {
var field;
switch (fieldType) {
case 'input':
field = `
<div class = "w-50 m-2">
<input
ng-change = "onChange()"
ng-model = "fieldValue"
class = "form-control"
>
<div>
`;
break;
case 'select':
field = `
<div class = "w-50 m-2">
<select
ng-change = "onChange()"
ng-model = "fieldValue"
class = "form-control"
>
<option value = "select1">select1</option>
<option value = "select2">select2</option>
</select>
<pre ng-bind = "getData()"></pre>
</div>
`;
break;
default:
field = '';
}
iElement.injector().invoke(function($compile) {
var isolateScope = iElement.scope().$new(true);
isolateScope.onChange = function() {
iElement.scope().setFieldValue(fieldsCounter, isolateScope.fieldValue);
console.info(iElement.scope().data);
}
iElement.append($compile(field)(isolateScope));
});
}
}
angular.bootstrap(
document.getElementById('root'), ['app']);<link rel = "stylesheet" href = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity = "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin = "anonymous">
<script src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div id = "root">
<wrapper></wrapper>
</div>