javascript - How can I create a directive that adds ng-class and ng-disabled on the target element based on a condition? -
i have following code:
app.directive "ngdisableonvar", ($compile) -> restrict: "a" terminal: true priority: 1000 replace:false scope: {} compile: compile = (element, attrs) -> cattr = attrs["ngdisableonvar"] element.attr("ng-class", "{'disabled': !#{cattr}}") element.attr("ng-disabled", "!#{cattr}") element.removeattr("ng-disable-on-var") pre: prelink = (scope, ielement, iattrs, controller) -> post: postlink = (scope, ielement, iattrs, controller) -> $compile(ielement)(scope)
i tried base code on answer given here. basically, i'd have following:
<input ngdisableonvar="somescopevariable>
and have replaced following:
<input ng-class="{'disabled': !somescopevariable}" ng-disabled="!somescopevariable">
something wrong, cause though have them applied element, they're disabled, though scope variable evaluates true. doing wrong?
edit: created plunker, first 2 buttons created ng-class , ng-disabled, , other 2 buttons, should have same things applied on them through use of directive.
here plunker version shared scope: http://plnkr.co/edit/tebcql20ubh5agj6nmil?p=preview
and here's 1 without shared scope:http://plnkr.co/edit/cpm55mrha8z6bx4gbxon?p=preview
the problem is, 1 without shared scope not update. how can make them update, , have conditions depend on variables passed arguments?
edit #2: i'm starting believe scope sharing correct way these 2 buttons should act, short of creating new directive encapsulates both buttons within it. not 100% sure though.
i go edit #2 because they related. if create them separate elements, need somehow pass related element each 1 => when click on 1 button, update , related element.
here modified first approach make work: http://plnkr.co/edit/kgyilatiw9xztezt9jv1?p=preview
in example, have pass related element each directive when click can update , related element:
related-element="btnforward"
i did modifications in directive:
scope: { reacton: "=", //use property binding instead of function binding relatedelement:"@" }, link: function(scope, element, attrs) { scope.toggle = function(){ scope.reacton = !scope.reacton;//toggle current element var relatedscope = $("#"+scope.relatedelement).scope();//get related element's scope , toggle relatedscope.reacton = !relatedscope.reacton; } //var cattr = attrs.ngdisablereacton; element.attr("ng-class", "{'disabled': !reacton}"); //use reacton instead property of current scope element.attr("ng-disabled", "!reacton"); element.attr("ng-click", "toggle()"); element.removeattr("ng-disable-react-on"); $compile(element)(scope); }
we don't need make things complex. create normal directive wrap 2 buttons.
myapp.directive("ngdisablereacton", function($compile) { return { restrict: "a", templateurl:"ngdisablereacton.html", scope: { can_go_back: "@" }, link: function(scope, element, attrs) { scope.goback = function(){ scope.can_go_back = false; } scope.gofwd = function(){ scope.can_go_back = true; } } } });
template:
<input type="button" value="go back" ng-click="goback()" ng-class="{'disabled': !can_go_back}" ng-disabled="!can_go_back"> <input type="button" value="go fwd" ng-click="gofwd()" ng-class="{'disabled': can_go_back}" ng-disabled="can_go_back">
another solution create parent directive container. solution most. approach, can freely change inner content of directive adding more buttons, more text,....(don't need hardcode template) parent directive works manager ensure there 1 active child @ time:
myapp.directive("ngdisablereactoncontainer", function() { //container directive manage child directives return { restrict: 'ea', replace: true, transclude: true,//use transclusion move inner content template template: '<div ng-transclude></div>', controller: function() { var children = []; this.selectchild = function(activechild) { //ensure 1 child active @ time activechild.active = true; angular.foreach(children, function(child) { if (child != activechild) { child.active = false; } }); } this.addchild = function(child) { children.push(child); } } }; }); myapp.directive("ngdisablereacton", function($compile) { return { restrict: "a", scope:{ active:"@" }, require: '^?ngdisablereactoncontainer', link: function(scope, element, attrs, controller) { scope.active = scope.active === 'true'; controller.addchild(scope);//register container scope.select = function(){//when element clicked, inform container toggle children accordingly. controller.selectchild(scope); } //add ng-class , ng-disabled based on requirement. element.attr("ng-class", "{'disabled': active}"); //use active instead property of current scope element.attr("ng-disabled", "active"); element.attr("ng-click", "select()"); element.removeattr("ng-disable-react-on"); $compile(element)(scope); } } });
using these directives simple:
<div ng-disable-react-on-container> <input ng-disable-react-on type="button" value="button 1" active="true" > <input ng-disable-react-on type="button" value="button 2" > <input ng-disable-react-on type="button" value="button 3" > </div>
Comments
Post a Comment