Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - Use attribute directive conditionally

I am using "draggable" directive to support image dragging. However, as per the role of the user, I need to disable image dragging for certain groups of users. I have used following code.

<!--draggable attribute is used as handle to make it draggable using jquery event-->           
<li  ng-repeat="template in templates" draggable id="{{template._id}}" type="template" class="template-box">            
<!-- Images and other fields are child of "li" tag which can be dragged.-->                    
</li> 

The method dragSupported is in the template scope and returns true or false. I don't want to create two big duplicate <li> elements by using ng-if for each value returned by dragSupported(). In other words, I am not looking for the following approach to solve this.

<!--draggable attribute is used as handle to make it draggable using jquery event-->           
<li ng-if="dragSupported() ==true"  ng-repeat="template in templates" draggable id="{{template._id}}" type="template" class="template-box">            
<!-- Images and other fields are child of "li" tag which can be dragged.-->                    
</li>
<!--remove "draggable" directive as user doesn't have permission to drag file -->
<li ng-if="dragSupported() !=true"  ng-repeat="template in templates"  id="{{template._id}}" type="template" class="template-box">            
<!-- Images and other fields are child of "li" tag which can be dragged.-->                    
</li>

Is there any other approach to avoid code duplicity?

like image 970
joy Avatar asked Sep 14 '13 04:09

joy


People also ask

How do you conditionally apply a directive?

Currently, there is NO way to conditionally apply a directive to a component. This is not supported. The components which you have created can be added or removed conditionally. There is already an issue created for the same with angular2 , so it should be the case with angular4 aswell.

What is Ng ATTR?

If expression is undefined, still fires directive link function, even though the directive is not added in the DOM. #16441.

What is attribute directive in Angular?

Angular attribute directives are a number of built-in directives that we can add to our HTML elements that give them a dynamic behavior. In summary, an attribute directive changes the appearance or behavior of a DOM element.

Which directive do we use to inform AngularJS about the parts controlled by it?

The ngRef attribute tells AngularJS to assign the controller of a component (or a directive) to the given property in the current scope. It is also possible to add the jqlite-wrapped DOM element to the scope. The ngRepeat directive instantiates a template once per item from a collection.


3 Answers

ng-attr-<attrName>

Support for conditionally declaring an HTML attribute is included with Angular as the dynamically-titled ng-attr-<attrName> directive.

Official Docs for ng-attr

Example

In your case, the code might look like this:

<li
    id="{{template._id}}"
    class="template-box"
    type="template"
    ng-repeat="template in templates"
    ng-attr-draggable="dragSupported() === true"
></li>

Demo

JSFiddle

This contains examples of usage for the following values: true, false, undefined, null, 1, 0, and "". Note how typically-falsey values may yield unexpected results.

like image 103
Walter Roman Avatar answered Oct 13 '22 10:10

Walter Roman


Thanks Jason for your suggestion. I took little different approach here. Since I don't want to change the "scope" variable therefore I used "attrs" to check if drag is allowed or not. Following is approach I tool which seems good so far.

Directive code:

app.directive('draggable', function () {
    return {
        // A = attribute, E = Element, C = Class and M = HTML Comment
        restrict: 'A',
        replace:true,
        link: function (scope, element, attrs) {

            if(attrs.allowdrag =="true")
            {
                element.draggable({
                cursor: 'move',
                helper: 'clone',
                class:'drag-file'
                });
            }

        }
    }
});

HTML Code:

<ul> 
         <!--draggable attribute is used as handle to make it draggable using jquery event-->           
        <li  ng-repeat="template in templates" draggable allowdrag="{{userHasPrivilege()}}" >            
                <!--Ohter code part of li tag-->                   

        </li> 

</ul>

Controller is having implementation of userHasPrivilege().

Not sure if this is correct way or not. Looking for thoughts.

like image 6
joy Avatar answered Oct 13 '22 10:10

joy


There is no way to directly add or remove an attribute from an element. However, you could create a directive that simply adds the attribute to the element when the condition is met. I've put something together that illustrates the approach.

Demo: http://jsfiddle.net/VQfcP/31/

Directive

myApp.directive('myDirective', function () {
  return {
    restrict: 'A',
    scope: {
        canDrag: '&'
    },
    link: function (scope, el, attrs, controller) {
        /*
$parent.$index is ugly, and it's due to the fact that the ng-repeat is being evaluated 
first, and then the directive is being applied to the result of the current iteration      
of the repeater.  You may be able to clean this by transcluding the repeat into the 
directive, but that may be an inappropriate separation of concerns. 
You will need to figure out the best way to handle this, if you want to use this approach.  
  */
        if (scope.canDrag&& scope.canDrag({idx: scope.$parent.$index})) {
            angular.element(el).attr("draggable", "draggable");
        }
    }
  };
});

HTML

<ul>
    <!-- same deal with $parent -->
    <li ng-repeat="x in [1, 2, 3, 4, 5]" my-directive="true" can-drag="checkPermissions(idx)">{{$parent.x}}</li>
</ul>

Controller

function Ctl($scope) {
   $scope.checkPermissions = function(idx) {
     // do whatever you need to check permissions
     // return true to add the attribute
   }
}
like image 3
Jason Avatar answered Oct 13 '22 09:10

Jason