我需要动态地向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>
我的步骤:
var isolateScope = iElement.scope().$new(true);
ng-change
,在父作用域调用函数
isolateScope.onChange = function() {
iElement.scope().setFieldValue(fieldsCounter, isolateScope.fieldValue);
}
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.log(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>