wake-up-neo.com

AngularJS - Verwenden Sie die Attributdirektive bedingt

Ich verwende "Draggable" Direktive, um das Ziehen von Bildern zu unterstützen. Gemäß der Rolle des Benutzers muss ich jedoch das Ziehen von Bildern für bestimmte Benutzergruppen deaktivieren. Ich habe folgenden Code verwendet.

<!--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> 

Die Methode dragSupported befindet sich im Vorlagenbereich und gibt true oder false zurück. Ich möchte nicht zwei große <li>-Elemente erstellen, indem ich ng-if für jeden von dragSupported() zurückgegebenen Wert verwende. Mit anderen Worten, ich suche nicht nach dem folgenden Ansatz, um dieses Problem zu lösen. 

<!--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>

Gibt es einen anderen Ansatz, um die Duplizität von Code zu vermeiden? 

53
joy

ng-attr-<attrName>

Die Unterstützung für das bedingte Deklarieren eines HTML-Attributs ist in Angular als dynamisch ng-attr-<attrName>-Direktive enthalten.

Offizielle Dokumente für ng-attr

Beispiel

In Ihrem Fall könnte der Code so aussehen:

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

Demo

JSFiddle

Dies enthält Beispiele für die Verwendung der folgenden Werte: true, false, undefined, null, 1, 0 und "". Beachten Sie, wie typische Falsey-Werte zu unerwarteten Ergebnissen führen können.

55
Walter Roman

Danke Jason für deinen Vorschlag. Ich bin hier etwas anders vorgegangen. Da ich die "scope" -Variable nicht ändern möchte, habe ich mit "attrs" geprüft, ob Ziehen erlaubt ist oder nicht. Es folgt ein Ansatz-I-Werkzeug, das bisher gut erscheint. 

Richtliniencode:

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 Quelltext:

<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>

Der Controller hat die Implementierung von userHasPrivilege ().

Nicht sicher, ob dies richtig ist oder nicht. Gedanken suchen. 

4
joy

Es gibt keine Möglichkeit, ein Attribut direkt einem Element hinzuzufügen oder daraus zu entfernen. Sie können jedoch eine Direktive erstellen, die das Attribut einfach dem Element hinzufügt, wenn die Bedingung erfüllt ist. Ich habe etwas zusammengestellt, das den Ansatz veranschaulicht.

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

Richtlinie

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
   }
}
3
Jason

Ich habe einen anderen Ansatz gewählt, da die vorherigen Beispiele für mich nicht funktionierten. Vielleicht hat es mit der Verwendung von benutzerdefinierten Anweisungen zu tun? Vielleicht kann das jemand aufklären.

In meinem speziellen Beispiel verwende ich UI-Grid, aber nicht alle UI-Grids sollten Paginierung verwenden. Ich übergebe ein "paginated" -Attribut und dann kompiliere $ die Direktive basierend auf true/false. Scheint ziemlich brutal, aber hoffentlich kann es die Menschen in eine positive Richtung bringen.

HTML

<sync-grid service="demand" paginated="true"></sync-grid>

Richtlinie

angular
    .module('app.directives')
    .directive('syncGrid', ['$compile', SyncGrid]);

function SyncGrid($compile){
    var nonPaginatedTemplate = '' +
        '<div>' +
        '   <div ui-grid="gridOptions" class="grid"></div>' +
        '</div>';

    var paginatedTemplate = '' +
        '<div>' +
        '   <div ui-grid="gridOptions" class="grid" ui-grid-pagination></div>' +
        '</div>';


    return {
        link: link,
        restrict: 'E',
        replace: true
    };

    function link(scope, element, attrs) {

        var isPaginated = attrs['paginated'];

        var template = isPaginated ? paginatedTemplate : nonPaginatedTemplate;
        var linkFn = $compile(template);
        var content = linkFn(scope);
        element.append(content);

        // Continue with ui-grid initialization code
        // ...

    }
}
0
Will Lovett