Как вызвать директивную функцию из контроллера в angularJS? - PullRequest
0 голосов
/ 05 июня 2018

В моей директиве есть функция обновления модели, которую я хочу вызвать из контроллера.Как получить доступ к функции директивы с контроллера?Я могу вызвать изменение модели, но для этого мне нужно выполнить событие нажатия.

Ниже мой код:

<div ng-if="((individualDropdown && YesRadio) || FolderDropdown)">
  <searchable-multiselect display-attr="infoMarketCodeWithName" 
    selected-items="formData.market" 
    all-items="allMarkets" 
    add-item="addMarketToList(item,allMarkets)" 
    remove-item="removeMarketFromList(item,allMarkets)" 
    ng-disable="NoRadio || NotSureRadio"
    ng-model="formData.market" name="marketDropdown">
  </searchable-multiselect>
</div>

Код директивы и вызываемая функция updateSelectedItems

app.directive("searchableMultiselect", ['$timeout', '$filter', function($timeout, $filter) {
        return {
          templateUrl: "Templates/SearchableMultiselect.html",
          require: 'ngModel',
          restrict: "AE",
          scope: {
            displayAttr: "@", //one way binding & only expression
            selectedItems: "=", //two way binding & expects model name
            allItems: "=",
            readOnly: "=",
            addItem: "&",
            removeItem: "&", //method binding               
          },
          link: function(scope, element, attrs) {
            element.bind('click', function(event) {
              event.stopPropagation();
            });
            scope.updateSelectedItems = function(obj) {
              console.log(scope.allMarkets);
              //code goes here
            }
          }
        ])

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Если в директиве используется ngModelController, атрибут selected-items является избыточным:

<div ng-if="((individualDropdown && YesRadio) || FolderDropdown)">
  <searchable-multiselect
    display-attr="infoMarketCodeWithName" 
    ̶s̶e̶l̶e̶c̶t̶e̶d̶-̶i̶t̶e̶m̶s̶=̶"̶f̶o̶r̶m̶D̶a̶t̶a̶.̶m̶a̶r̶k̶e̶t̶"̶
    ng-model="formData.market"
    all-items="allMarkets" 
    add-item="addMarketToList(item,allMarkets)" 
    remove-item="removeMarketFromList(item,allMarkets)" 
    read-only="NoRadio || NotSureRadio"
    name="marketDropdown">
  </searchable-multiselect>
</div>

Используйте метод $setViewValue для установкивыбранное значение:

    require: 'ngModel',
    restrict: "E",
    scope: {
        displayAttr: "@", //one way binding & only expression
        ̶s̶e̶l̶e̶c̶t̶e̶d̶I̶t̶e̶m̶s̶:̶ ̶"̶=̶"̶,̶ ̶/̶/̶t̶w̶o̶ ̶w̶a̶y̶ ̶b̶i̶n̶d̶i̶n̶g̶ ̶&̶ ̶e̶x̶p̶e̶c̶t̶s̶ ̶m̶o̶d̶e̶l̶ ̶n̶a̶m̶e̶
        ngModel: "<",
        allItems: "<",
        addItem: "&",
        removeItem: "&", //method binding               
        readOnly: "<",
    },
    ̶l̶i̶n̶k̶:̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶s̶c̶o̶p̶e̶,̶ ̶e̶l̶e̶m̶e̶n̶t̶,̶ ̶a̶t̶t̶r̶s̶)̶ ̶{̶
    link: function(scope, element, attrs, ngModel) {
        element.bind('click', function(event) {
            event.stopPropagation();
        });

        scope.updateSelectedItems = function(obj) {
          console.log(scope.allMarkets);
          //code goes here
          ngModel.$setViewValue(obj);
        }
    }

Для получения дополнительной информации см.

0 голосов
/ 05 июня 2018

С точки зрения хорошей практики AngularJS, вы должны применять принцип разделения интересов, не устанавливая такую ​​сильную зависимость от контроллера, чтобы знать имена функций в директивах и тому подобное.

Одна альтернатива - использовать событие-принципиальный подход, при котором директива отправляет событие, которое захватывается контролируемым и на которое выполняется действие, причем цикл замыкается путем обновления модели.

app.directive("searchableMultiselect", ['$timeout', '$filter', function($timeout, $filter) {
    return {
        templateUrl: "Templates/SearchableMultiselect.html",
        require: 'ngModel',
        restrict: "AE",
        scope: {
            displayAttr: "@", //one way binding & only expression
            selectedItems: "=", //two way binding & expects model name
            allItems: "=",
            readOnly: "=",
            addItem: "&",
            removeItem: "&", //method binding               
        },
        link: function(scope, element, attrs) {
            element.bind('click', function(event) {
                event.stopPropagation();
            });

            scope.updateSelectedItems = function(obj) {
                console.log(scope.allMarkets);
                scope.$emit("updateSelectedItems", scope.allMarkets);
            }
        }
    }   
}])

А в контроллере:

app.controller("ctrl", ['$scope', function ($scope) {
    $scope.$on("updateSelectedItems", function (event, allMarkets) {
        // Do stuff with data
        // Update data model bound to directive if necessary
    });
}])

Надеюсь, это имеет смысл:)

...