How to set a default value in an AngularJS Directi

2019-06-20 02:07发布

问题:

In AngularJS, I have the following scenario where a directive can accept an optional boolean parameter which should default to true by default, whenever it is not specified.

Example:

<my-directive data-allow-something="false">
    ... this works as expected as no default value should be set in this case ...
</my-directive>

<my-directive>
    ... but in this case i'd like allowSomething to equal true  ...
</my-directive>

I've tried the following approach, but for some reason the true value doesn't stick on allowSomething. making it a '=?' optional two way binding doesn't work neither as my passed value should be a concrete true/false and not a field reference.

angular.module('myApp').directive('myDirective') {
    ...
    controller: function($scope){
        if (!$scope.allowSomething)
            $scope.allowSomething = true;
    },
    ....
    scope: function(){
        allowSomething: '@'
    }
    ...
}

I'm sure there should be a simple way to achieve this, so what am i missing?

The solutions given at the following ticket: AngularJS directive with default options are not sufficient for my needs since the $compile function will prevent the link function from working. plus, the passed-in boolean value is not a reference type and i cannot give it a two-way binding.

回答1:

I think a better way to check that value is look for an undefined value like this:

controller: function($scope){
    if (angular.isUndefined($scope.allowSomething))
        $scope.allowSomething = true;
}

I had the same issue once and this worked for me. I think the best method is to use angular's methods for handling things.



回答2:

This is how I have been doing it:

html:

<my-directive allow-something="false"></my-directive>
<my-directive></my-directive>

directive:

angular
.module('app')
.directive('myDirective', function() {

var defaults = {
  allowSomething: true
};

return {
  restrict: 'E',
  templateUrl: '',
  scope: {},
  compile: function() {
    return {
      pre: function(scope, el, attrs) {
        scope.allowSomething = attrs.allowSomething || defaults.allowSomething;
      },

      post: function(scope, el) {
        // this is link
        // scope.allowSomething = default or whatever you enter as the attribute "false"
      }
    };
  }
};
}

The pre is fired before anything happens then the post is like the link function. This has allowed me to do dynamic things based on the attributes I set.



回答3:

I think you can do something like this:

 scope : true,
  link : function(scope, element, attrs){
    scope.allowSomething = $parse(attrs.allowSomething)(scope) || true;
    console.log(scope)
  }


回答4:

Given your template is

<body>
  <my-directive></my-directive>
  <!-- <my-directive allow-something="false"></my-directive> -->
</body>

Then you can either use link (preferred if no interaction with other directives is needed) or controller.

angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      scope: {},
      link: function(scope, element, attrs) {
        scope.allowSomething = ('allowSomething' in attrs) ? attrs.allowSomething : true;
      }, 
      template: '<div>allow:{{ allowSomething }}</div>'
    };
  });  

// or

angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      scope: {
        allowSomething: '@'
      },
      controller: function($scope, $timeout) {
        $timeout(function() {
          if (angular.isUndefined($scope.allowSomething)) {
            $scope.allowSomething = true;
          }
        });
      },  
      template: '<div>allow:{{ allowSomething }}</div>'
    }; 
  });