动态添加元素到Angularjs

问题描述 投票:0回答:1

我需要动态地向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 angularjs
1个回答
0
投票

我的步骤:

  • 为创建的元素定义了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.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>
© www.soinside.com 2019 - 2024. All rights reserved.