Re: Default Directive Scope Values?

7,300 views
Skip to first unread message

Mark Holtzhausen

unread,
Sep 6, 2012, 6:46:32 AM9/6/12
to ang...@googlegroups.com
That will work for surface implementations.  What if you need to access the passed/default value in the controller function? The controller function seems to fire before the scope bindings are applied. 

On Tuesday, July 17, 2012 3:16:04 AM UTC+2, Andy Joslin wrote:
You could do 

template: '<div>test: {{test || 'defaultValue'}}</div>

Jim Cooper

unread,
Apr 5, 2013, 9:41:11 PM4/5/13
to ang...@googlegroups.com
I wondered the same thing.  It does work to set the scope values in the link function, btw.  Just not sure if that's the intended approach.

On Monday, July 16, 2012 5:47:22 PM UTC-6, ItsLeeOwen wrote:
Is there an intended way to set default values on directive scope properties if they aren't set in the attributes?  Testing in the constructor does not work.


<my-directive></my-directive>

function MyDirective( $scope )
{
  if( $scope.test == undefined )
    $scope.test = 'Hello';
}

MyModule.directive('myDirective', function()
{
    return {
        restrict: 'E',
        replace: true,
        scope: {
          test: '@'
        },
        template: '<div>test: {{ test }}</div>',
        controller: 'MyDirective'
    };
});

Josh David Miller

unread,
Apr 6, 2013, 2:06:14 PM4/6/13
to angular
Hello!

From my perspective, your best bet is to use $observe:

$attrs.$observe( 'test', function( val ) {
  if ( ! angular.isDefined( val ) ) {
    $scope.test = 'Hello';
  }
});

The controller method only gets executed once; $observe will get executed on each interpolated change. This will allow you to react to values that were once defined and have become undefined or were once populated and are now blank, etc.

Also, the controller is executed *before* the attributes are interpolated, so it will always be undefined when your controller runs. What's actually happening here is that you're assigning a scope property that just never gets overwritten by a new value because one wasn't provided. If you wanted more complicated logic (like validation) then you couldn't use that method at all.

There's also the added benefit that this method will work seamlessly without the isolate scope magic, so we can follow the same pattern in child scope directives. We only need one trick in the bag:

$attrs.$observe( 'test', function( val ) {
    $scope.test = angular.isDefined( val ) ? val : 'Hello';
});

Josh


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Travis Parks

unread,
Apr 16, 2014, 3:11:02 PM4/16/14
to ang...@googlegroups.com
I have tried this approach in production and ran into the following error messages: Error: [$compile:nonassign] Expression 'undefined' used with directive '' is non-assignable!

After a little research, I discovered this was due to two-way binding.
Since the attribute does not appear in the HTML, it binds the attribute to undefined.
When the scope gets updated, the two-ways binding tries to update undefined, which is illegal.

This error does not occur if you use an expression (true, false, 1 + 2) because the value is defined.
Reply all
Reply to author
Forward
0 new messages