wake-up-neo.net

AngularJS-Direktive mit Standardoptionen

Ich fange gerade mit anglejs an und arbeite daran, einige alte JQuery-Plugins in Angular Direktiven umzuwandeln. Ich möchte eine Reihe von Standardoptionen für meine (Element-) Direktive definieren, die kann überschrieben werden, indem der Optionswert in einem Attribut angegeben wird.

Ich habe mich umgesehen, wie andere dies getan haben, und in der Bibliothek angle-ui scheint i.bootstrap.pagination etwas Ähnliches zu tun.

Zunächst werden alle Standardoptionen in einem konstanten Objekt definiert:

.constant('paginationConfig', {
  itemsPerPage: 10,
  boundaryLinks: false,
  ...
})

Dann wird eine getAttributeValue Utility-Funktion an den Direktiven-Controller angehängt:

this.getAttributeValue = function(attribute, defaultValue, interpolate) {
    return (angular.isDefined(attribute) ?
            (interpolate ? $interpolate(attribute)($scope.$parent) :
                           $scope.$parent.$eval(attribute)) : defaultValue);
};

Schließlich wird dies in der Verknüpfungsfunktion verwendet, um Attribute als einzulesen

.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) {
    ...
    controller: 'PaginationController',
    link: function(scope, element, attrs, paginationCtrl) {
        var boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks,  config.boundaryLinks);
        var firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true);
        ...
    }
});

Dies scheint ein ziemlich kompliziertes Setup für etwas wie Standard zu sein, das eine Reihe von Standardwerten ersetzen möchte. Gibt es andere Möglichkeiten, dies zu tun, die üblich sind? Oder ist es normal, immer eine Utility-Funktion wie getAttributeValue und Analyseoptionen auf diese Weise zu definieren? Mich interessiert, welche unterschiedlichen Strategien Menschen für diese gemeinsame Aufgabe haben.

Außerdem ist mir nicht klar, warum der Parameter interpolate erforderlich ist.

142
Ken Chatfield

Sie können die Funktion compile verwenden - Attribute lesen, wenn sie nicht gesetzt sind - sie mit Standardwerten füllen.

.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) {
    ...
    controller: 'PaginationController',
    compile: function(element, attrs){
       if (!attrs.attrOne) { attrs.attrOne = 'default value'; }
       if (!attrs.attrTwo) { attrs.attrTwo = 42; }
    },
        ...
  }
});
107
OZ_

Verwenden Sie die =? Flag für die Eigenschaft im Gültigkeitsbereich der Direktive.

angular.module('myApp',[])
  .directive('myDirective', function(){
    return {
      template: 'hello {{name}}',
      scope: {
        // use the =? to denote the property as optional
        name: '=?'
      },
      controller: function($scope){
        // check if it was defined.  If not - set a default
        $scope.name = angular.isDefined($scope.name) ? $scope.name : 'default name';
      }
    }
  });
254
Hunter

Ich verwende AngularJS v1.5.10 und habe festgestellt, dass die Kompilierungsfunktion preLink zum Festlegen von Standardattributwerten ziemlich gut funktioniert.

Nur eine Erinnerung:

  • attrs enthält die DOM-Attributwerte raw, die immer entweder undefined oder Zeichenfolgen sind.
  • scope enthält (unter anderem) die DOM-Attributwerte geparst gemäß der bereitgestellten Isolate-Scope-Spezifikation (=/</@/etc.).

Kurzer Ausschnitt:

.directive('myCustomToggle', function () {
  return {
    restrict: 'E',
    replace: true,
    require: 'ngModel',
    transclude: true,
    scope: {
      ngModel: '=',
      ngModelOptions: '<?',
      ngTrueValue: '<?',
      ngFalseValue: '<?',
    },
    link: {
      pre: function preLink(scope, element, attrs, ctrl) {
        // defaults for optional attributes
        scope.ngTrueValue = attrs.ngTrueValue !== undefined
          ? scope.ngTrueValue
          : true;
        scope.ngFalseValue = attrs.ngFalseValue !== undefined
          ? scope.ngFalseValue
          : false;
        scope.ngModelOptions = attrs.ngModelOptions !== undefined
          ? scope.ngModelOptions
          : {};
      },
      post: function postLink(scope, element, attrs, ctrl) {
        ...
        function updateModel(disable) {
          // flip model value
          var newValue = disable
            ? scope.ngFalseValue
            : scope.ngTrueValue;
          // assign it to the view
          ctrl.$setViewValue(newValue);
          ctrl.$render();
        }
        ...
    },
    template: ...
  }
});
1
Keego