Varsayılan seçeneklerle AngularJS yönergesi


145

Angularjs ile yeni başlıyorum ve birkaç eski JQuery eklentisini Angular yönergelerine dönüştürmek için çalışıyorum. (Element) yönergem için, bir öznitelikte seçenek değeri belirtilerek geçersiz kılınabilen bir dizi varsayılan seçenek tanımlamak istiyorum.

Başkalarının bunu nasıl yaptığını araştırdım ve angular-ui kitaplığında ui.bootstrap.pagination da benzer bir şey gibi görünüyor.

Öncelikle tüm varsayılan seçenekler sabit bir nesnede tanımlanır:

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

Ardından getAttributeValueyönerge denetleyicisine bir yardımcı program işlevi eklenir:

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

Son olarak, bu bağlantı işlevinde öznitelikleri şu şekilde okumak için kullanılır:

.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);
        ...
    }
});

Bu, bir dizi varsayılan değeri değiştirmek isteyen standart bir şey için oldukça karmaşık bir kurulum gibi görünüyor. Bunu yapmanın yaygın olan başka yolları var mı? Veya her zaman gibi bir yardımcı program işlevini tanımlamak getAttributeValueve seçenekleri bu şekilde ayrıştırmak normal mi? İnsanların bu ortak görev için hangi farklı stratejilere sahip olduğunu öğrenmekle ilgileniyorum.

Ayrıca, bonus olarak, interpolateparametrenin neden gerekli olduğu konusunda net değilim .

Yanıtlar:


108

compileAyarlanmamışlarsa işlev okuma özniteliklerini kullanabilirsiniz - bunları varsayılan değerlerle doldurun.

.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; }
    },
        ...
  }
});

1
Teşekkürler! Öyleyse ui.bootstrap.pagination, olayların neden daha karmaşık bir şekilde yürüdüğüne dair herhangi bir fikriniz var mı? Derleme işlevi kullanılırsa, daha sonra yapılan herhangi bir öznitelik değişikliğinin yansıtılmayacağını düşünüyordum, ancak bu aşamada yalnızca varsayılanlar ayarlandığı için bu doğru görünmüyordu. Sanırım burada bazı ödünleşmeler yapılıyor olmalı.
Ken Chatfield

3
@KenChatfield'daki @KenChatfield, compiledeğer elde etmek için enterpolasyon yapılması gereken (ifade içeren) nitelikleri okuyamazsınız. Ancak, yalnızca özniteliğin boş olup olmadığını kontrol etmek istiyorsanız - sizin için herhangi bir değiş tokuş olmadan çalışacaktır (enterpolasyon özniteliği ifadeli dize içermeden önce).
OZ_

1
Fantastik! Açık açıklamanız için çok teşekkürler. Gelecekteki okuyucular için, orijinal soruya teğet olmasına rağmen, ui.bootstrap.paginationörnekteki 'interpolate' parametresinin ne yaptığına dair bir açıklama için şu çok yararlı örneği buldum: jsfiddle.net/EGfgH
Ken Chatfield

Bu çözüm için çok teşekkürler. Seçeneğe ihtiyacınız linkvarsa, yine de seçeneğinizde bir işlev döndürebileceğinizi unutmayın compile. Burada doc
mneute

4
Unutmayın, özniteliklerin şablondan geçirilecekleri için değerlere ihtiyacı vardır. Bir dizi fe geçiyorsanız bunun attributes.foo = '["one", "two", "three"]'yerine geçmelidirattributes.foo = ["one", "two", "three"]
Dominik Ehrenberg

263

=?Yönergenin kapsam bloğundaki özellik için bayrağı kullanın .

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';
      }
    }
  });

4
=?1.1.x
Mikhail Radionov

34
Senin nitelik kabul olsaydı trueveya falsedeğerler olarak, siz (Sanırım) olur mesela kullanmak istiyorum $scope.hasName = angular.isDefined($scope.hasName) ? $scope.hasName : false;bunun yerine.
Paul D. Waite

22
Not: yalnızca iki yönlü ciltleme ile çalışır, örneğin =?tek yönlü ciltleme ile çalışmaz @?.
Justus Romijn

20
sadece şablonda da yapılabilir: şablon: 'merhaba {{isim || \ 'varsayılan ad \'}} '
Vil

4
Varsayılan değer kontrolörde linkmi yoksa işlevde mi ayarlanmalıdır ? Anladığıma göre, linkbir $scope.$apply()döngü sırasında atama yapmak bir döngüden kaçınmalı , değil mi?
Augustin Riedinger

2

AngularJS v1.5.10 kullanıyorum ve preLinkderleme işlevinin varsayılan öznitelik değerlerini ayarlamak için oldukça iyi çalıştığını buldum .

Sadece bir hatırlatıcı:

  • attrsher zaman ya da dizelerden biri olan ham DOM özellik değerlerini tutar undefined.
  • scope(diğer şeylerin yanı sıra) sağlanan izolat kapsamı belirtimine ( / / / vb.) göre ayrıştırılan DOM özniteliği değerlerini tutar .=<@

Kısaltılmış snippet:

.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: ...
  }
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.