Динамическое добавление элементов в Angularjs

Мне нужно динамически добавлять элементы в 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>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
40
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мои шаги:

  • определил 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>

Другие вопросы по теме