Set initial model value for an angular directive - angularjs

I have a directive:
<div class="my-switch-on-off"
data-caption="Back"
data-section="frames"
data-module="back"
>
</div>
And its template is a checkbox:
<input type="checkbox" class="switch"
ng-model="isActive"
ngTrueValue="true"
ngFalseValue="false"
ng-change="toggleVisibility(section, module)"
/>
This directive is used around 10 times. All the checkboxes are not checked. I want to have a condition in my link function so I can have some of them checked. What is the right way to do that? Should I access the model and change its value or should I make the checkbox checked using jQuery lite? My directive is like:
angular.directive("mySwitchOnOff", [
function() {
return {
restrict: "C",
scope: {},
templateUrl: "template.html",
link: function(scope, element, attrs) {
return scope.toggleVisibility = function(section, module) {
};
}
};
}
]);
Update, jsfiddle thx to #deitch
What I want is when the data-section=extensions the checkbox of the template to be checked
http://jsfiddle.net/m0q28vjc/2/

Oh definitely set the value of the ng-model in the scope.
In your directive
angular.directive("mySwitchOnOff", [
function() {
return {
restrict: "C",
scope: {},
templateUrl: "template.html",
link: function(scope, element, attrs) {
// set the value of toggled based on attrs
scope.isActive = attrs.section === "extensions";
return scope.toggleVisibility = function(section, module) {
};
}
};
}
]);
Here is a fiddle with the correct structure
http://jsfiddle.net/m0q28vjc/4/

Related

How to pass ng-model value in radio button from ng-repeat into link function on directive

I want one of the Radio Button to be selected once the page is loaded, from another question on stackoverflow i found that Radio Button will be check if the value of the input attribute is equal to the value of model applied on the Radio Button. But i am unable to access the model($parent.selectedItem) on Radio Button in link function inside child directive. Api i used in example is a placeholder but in realtime i will have a property selected which will be true/false which I want to bind to the $parent.selectedItem
var mainApp = angular.module('mainApp', []);
mainApp.factory('myFactory', function ($http) {
var myFactory = {
myMethod: function () {
var promise = $http.get('https://jsonplaceholder.typicode.com/users').then(function (response) {
return response.data;
});
return promise;
}
};
return myFactory;
});
Controller:
mainApp.controller('myController', function ($scope, myFactory) {
myFactory.myMethod().then(function (result) {
$scope.data = result
})
});
Directives:
mainApp.directive('parent', function (myFactory) {
return {
restrict: 'E',
replace: true,
scope: true,
templateUrl: 'parent.html',
link: function (scope, element, attrs, ctrl) {
myFactory.myMethod().then(function (result) {
scope.Model = result
})
}
}
});
mainApp.directive('child', function () {
return {
restrict: 'E',
scope: {
Model: '=ngModel'
},
replace: true,
require: 'ngModel',
templateUrl: 'child.html',
link: function (scope, element, attrs, ctrl) {
// unable to access scope.selectedItem
console.log(scope.selectedItem)
}
}
});
HTML:
// mainpage.html
<body ng-app="mainApp"><parent></parent></body>
//parent.html
<div><child ng-model = "Model"></child></div>
//child.html
<div ng-repeat="item in Model"><input type="radio" name="itemSelected"
ng-value="item" ng-model="$parent.selectedItem"/>{{item.name}}</div>
when you require ngModel in the child directive, what you're basically requiring is its controller, this controller is then injected into your link function as the 4th parameter, in your case the ctrl argument.
so right now your ngModel might work, but it is not in your link function because you're expecting it to exist on the scope as selectedItem, but on your scope you have declared it as Model (not selectedItem). However, you also have access to the ngModel controller, so you could ask for its value there through its controller: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController.
ex:
ctrl.$viewValue
// or
ctrl.$modelValue
//whichever serves your purpose

AngularJs - Bootstrap Toggle not able to get check box values

I am using Bootstrap Toggle for my AngularJs project. I created angular directive for this plugin.
myApp.directive('iosToggle', function(){
return {
restrict: 'A',
link: function(scope, element, attrs){
$(element).bootstrapToggle(scope.$eval(attrs.iosToggle));
}
};
});
and using directive in my view
<input type="checkbox" id="myInterview" data-ios-toggle="toggle" data-style="ios" data-onstyle="info" data-size="small" data-on="On" data-off="Off" ng-model="myData.myInterview">
I am getting same design and able to on or off, but When i submit the form, i am not getting check box values.
Yes, I have updated my directive with $watch on change and then updated the model. It works.
myApp.directive('iosToggle', function($timeout){
return {
restrict: 'A',
transclude: true,
replace: false,
require: 'ngModel',
link: function ($scope, $element, $attr, ngModel) {
// update model from Element
var updateModelFromElement = function() {
// If modified
var checked = $element.prop('checked');
if (checked !== ngModel.$viewValue) {
// Update ngModel
ngModel.$setViewValue(checked);
$scope.$apply();
}
};
// Update input from Model
var updateElementFromModel = function() {
$element.trigger('change');
};
// Observe: Element changes affect Model
$element.on('change', function() {
updateModelFromElement();
});
// Observe: ngModel for changes
$scope.$watch(function() {
return ngModel.$viewValue;
}, function() {
updateElementFromModel();
});
// Initialise BootstrapToggle
$timeout(function() {
$element.bootstrapToggle();
});
}
};
});

how to pass variable from controller to directive using click event in angularjs

i am using directive concept in angularjs to pass data varible from controller to directive.i am writing one html page and controller,directive in angularjs.
test.html:
<div ng-controller="myController"
data-angular-treeview="true"
data-tree-model="roleList"
data-node-id="roleId"
data-tree-id="mytree"
data-node-label="roleName"
data-node-children="children"
data-ng-click="selectNode(currentNode)"
>
</div>
testcontroller.js:
(function(){
app.controller('myController', function($scope,$http,TreeService){
$scope.selectNode=function(val)
{
$scope.nodeval=val.roleName;
alert("select:"+$scope.nodeval);
};
});
})();
testdirective.js:
app.directive('tree1', function($rootScope) {
function compile(scope, element, attributes) {
return {
post:function(scope, iElement, iAttrs) {
iElement.bind('click', function() {
alert("click: "+scope.node);
});
}
};
}
return {
compile: compile,
scope: {
},
restrict: 'AE',
};
});
here i am getting selected node name in testcontroller.js but i want to pass that nodename in my directive so please suggest me how to this.
Thanks
What i would do is define inside the directive isolated scope an attribute like this:
scope: {
node: '='
}
And inside the view controller have a node initialized as $scope.node = {}; and with the click event change the value of the local $scope.node to the node you are interested in, and as the directive recieved the reference to the $scope.node attribute inside the view controller, it would automatically update itself
<div test-directive node-value="node"></div>
isolate scope directive:
directive('testDirective', function(){
return {
restrict: 'EA',
scope: {
nodeValue: '='
},
link: function(scope, element, attrs){
console.log(scope.nodeValue);
}
}
Access controller scope:
directive('testDirective', function(){
return {
restrict: 'EA',
link: function(scope, element, attrs){
console.log(scope.$eval(attrs['nodeValue']));
}
}

Require controller in directive when terminal is true

I can't load controller's parent in a directive. I have two directives: h-menu and h-menu-item. h-menu uses a controller, and h-menu-item requires that controller.
But h-menu directive has terminal = true, and with this I can't load controller. When I set terminal to false, I can load the controller.
JsFiddle: http://jsfiddle.net/gspVe/4/
html:
<div ng-app="test">
<h-menu>
<h-menu-item>
</h-menu-item>
</h-menu>
</div>
Here is the code js:
angular.module("test", [])
.controller("hMenu", function () {
this.msg = "controller was loaded";
return this;
})
.directive("hMenu", function($compile) {
return {
restrict: "E",
// comment this and controller will be loaded
terminal: true,
controller: "hMenu",
require: "hMenu",
link: function (scope, element, attrs) {
var ul = $("<ul/>");
ul.append(element.children());
$compile(ul)(scope);
element.replaceWith(ul);
}
};
})
.directive("hMenuItem", function($compile) {
return {
restrict: "E",
terminal: true,
require: "?^hMenu",
link: function (scope, element, attrs, controller) {
var li = $("<li/>");
if (controller)
li.html(controller.msg);
else
li.html("contoller not loaded!");
$compile(li)(scope);
element.replaceWith(li);
}
};
})
Just trying to understand what you're trying to do. If you want to replace HTML elements, why not use some of the facilities that a directive provides already?
For instance, it looks like you're trying to replace the directive elements with <ul> and <li>. Rather than define this as you've indicated, why couldn't you do the following:
angular.module("test", [])
.directive("hMenu", function() {
return {
restrict: "E",
transclude : true,
replace : true,
template : "<ul ng-transclude></ul>"
};
})
.directive("hMenuItem", function() {
return {
restrict: "E",
replace : true,
transclude : true,
template : '<li ng-transclude></li>'
};
})
Then, you can use the power of Angular to indicate menu items declaratively, for example:
<div ng-app="test">
<h-menu ng-init="menuitems=['Menu #1', 'Menu #2', 'Menu #3']">
<h-menu-item ng-repeat="m in menuitems">
{{m}}
</h-menu-item>
</h-menu>
</div>
This would show:
Menu #1
Menu #2
Menu #3
I've updated a jsfiddle at http://jsfiddle.net/gspVe/9/

ng-bind span not updated on changing the object's property

In the following code, i change the object's property on clicking the 'tab' element, but the corresponding ngbind span is not getting updated. Do i have to call some function to update the view?
HTML:
<html ng-app="splx">
...
<body ng-controller="Application">
<span ng-bind="obj.val"></span>
<tabpanel selector="obj">
<div tab value="junk">junk</div>
<div tab value="super">super</div>
</tabpanel>
</body>
</html>
JS:
var cf = angular.module('splx', []);
function Application($scope) {
$scope.obj = {val: "something"};
}
cf.directive('tabpanel', function() {
return {
restrict: 'AE',
scope: {
selector: '='
},
controller: ['$scope', function($scope) {}]
};
});
cf.directive('tab', function() {
return {
require: '^tabpanel',
restrict: 'AE',
scope: true,
link: function(scope, elem, attrs) {
elem.bind('click', function() {
scope.$parent.selector.val = "newthing";
});
}
};
});
cf.directive('tab', function() {
return {
require: '^tabpanel',
restrict: 'AE',
scope: true,
link: function(scope, elem, attrs) {
elem.bind('click', function() {
scope.$apply(function () {
scope.$parent.selector.val = "newthing";
});
});
}
};
});
That works for me. Just missing a little scope.$apply in there.
Might want to have a look at https://coderwall.com/p/ngisma if you find yourself using/having trouble with '$apply already in progress'.
If you want to change the value to what you clicked on, I'd do something like this:
scope.$parent.selector.val = attrs.tab;
As opposed to:
scope.$parent.selector.val = "newthing";
And then you can change your markup to look like this:
<tabpanel selector="obj">
<div tab="junk">junk</div>
<div tab="super">super</div>
</tabpanel>
Hope that helps!
First problem: you are not binding your controller to your app.
You need cf.controller('Application', Application);.
Also you need ng-controller="Application" in HTML on a parent of that span and the tabpanel directive.
Second problem: after changing that scope variable in your click event you need to
scope.$apply() to let Angular know something changed and it needs to $digest it.
You can check out my version here.

Resources