Добавление API в директиву AngularJS

Примечание: я воспроизвел свой код здесь в JS Bin

У меня есть директива, которая распечатывает массив элементов на веб-странице. Предположим, что строка 'console.log("добавлено") "на самом деле представляет собой сложную логику, и мы хотели, чтобы директива выполнялась каждый раз, независимо от того, какой контроллер ее использует. Он может сделать вызов AJX, чтобы указать, что новая запись была добавлена.

Так что я представляю, что в директиве есть функция, которая делает это. И вместо того, чтобы использовать "$scope.items" для добавления нового элемента, контроллер будет вызывать эту функцию в директиве. Если нет лучшего способа сделать это, можете ли вы сказать мне, как подойти к этому?

HTML:

<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body ng-app="app">
  <div ng-controller="MyCtrl">
    <input type="text" ng-model="newitem.name"/>
    <button type="button" ng-click="addNewItem(newitem)">Add Item</button>
    <menu items="items"/>
  </div>
</body>
</html>

JavaScript:

var app = angular.module("app", []);

app.controller('MyCtrl', function($scope) {
  $scope.items = [
    {name: "item1"},
    {name: "item2"},
    {name: "item3"},
    {name: "item4"}
  ];

  $scope.addNewItem = function(newItem) {
    $scope.items.push(angular.copy(newItem));
    console.log("added");  //PRETEND THIS IS COMPLEX LOGIC WE WANT MOVED TO DIRECTIVE
  };
});

app.directive("menu", function(){
  return {
    restrict: "E",
    scope: {
      items: "=" 
    },
    template: "<div ng-repeat='item in items'>{{item.name}}</div>"
  };
});

1 ответ

Обычно вы делаете ajax-запросы через сервисы.

Допустим, вы хотите сохранить добавленный элемент в базе данных через API REST, а затем получить ответ и проанализировать его в списке меню, после чего вы сделаете что-то вроде этого:

app.service('MenuService', function($http) {
  this.addItem = function(item) {
    return $http.post('/rest/menu', {menuItem: item});
  }
});

Вернуться в ваш контроллер:

app.controller('MyCtrl', function($scope, MenuService) {
  $scope.items = [
    {name: "item1"},
    {name: "item2"},
    {name: "item3"},
    {name: "item4"}
  ];

  $scope.addNewItem = function(newItem) {
    MenuService.addItem(newItem).then(function(itemFetchedFromWebService) {
      $scope.items.push(itemFetchedFromWebService);
    }, function(error) {console.log(error); });
  };
});

Если вам не нужно манипулировать dom больше, чем это делает директива ng-repeat, и вам также не нужно получать дополнительные данные через атрибуты, тогда вам не нужна эта директива. контроллер должен сделать работу уже.

редактировать

Если вы предпочитаете использовать директиву, вы можете использовать функцию ссылки:

app.directive("menu", function(MenuService){ //Note the added dependency
  return {
    restrict: "E",
    scope: {
      items: "=" 
    },
    template: "<div ng-repeat='item in items'>{{item.name}}</div>",
    link: function(scope) {
      scope.addNewItem = function(newItem) {
       MenuService.addItem(newItem).then(function(itemFetchedFromWebService){
        scope.items.push(itemFetchedFromWebService);
       }, function(error) {console.log(error); });
      };
    }
  };
});

Какую функцию связи вы можете использовать:

  • Текущий объект области (Изолированная область в вашем случае).
  • Элемент этой директивы (обернутый в объект angular.element), вы можете получить доступ к элементу dom с помощью "element[0]"
  • Объект, который содержит атрибуты элемента.

Есть еще 2 аргумента, которые вы можете использовать в своей функции ссылки: (выходит за рамки вопроса)

Четвертый аргумент позволяет вам использовать контроллеры другой директивы в текущем элементе или элементах parent/sibling.

Пятый аргумент - это функция transclude, которая позволяет вам манипулировать включенными элементами.

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