I am trying to create a directive modal so i can use on other place.
I want the modal to pop when user do something. I use ng-show to hide it.
my html
<my-modal ng-show="showModal" data-text="my text"></my-modal>
my directive
angular.module('myApp').directive('myModal', ['$modal',
function($modal) {
return {
restrict: 'E',
scope: false,
link: function(scope, elem, attrs) {
$modal({
template: '<div>{{scope.attrs.text}}</div>'
scope: scope,
});
}
};
}
]);
My controller
angular.module('myApp').controller('tCtrl', ['$scope',
function($scope) {
$scope.showModal = false;
}
}])
For some reason, I can't hide modal and it always pops when the page first loads. How do I successfully hide it when the page first loads? Thanks for the help!
The link function runs as soon as the directive is loaded, so in your case, if you only want to show your modal once $scope.showModal = true, you have to modify your directive:
angular.module('myApp').directive('myModal', ['$modal',
function($modal) {
return {
restrict: 'E',
scope: {
display: '=',
},
link: function(scope, elem, attrs) {
scope.$watch('display', function(newVal, oldVal) {
if(newVal !== oldVal && newVal) {
$modal({
template: '<div>{{scope.attrs.text}}</div>',
scope: scope
});
}
});
}
};
}
]);
And change your html to
<my-modal display="showModal" data-text="my text"></my-modal>
Related
I have created a directive for showing a X besides a text box for clearing the data inside the text box,
Directive JS
angular.module(appName).directive('clrTxt', function () {
return {
restrict: 'E',
replace: true,
scope: {
cntrlas: '=',
mdlval: '='
},
link: function (scope, elem, attrs, ctrl) {
scope.cleartxt = function () {
scope.cntrlas[scope.mdlval] = '';
}
},
template: '<button class="close-icon" type="reset" id="closeicon" ng-click="cleartxt()" ><img src="/resources/img/quote-tool-close.png" class="clear-icon"></button>'
};
});
HTML
<input type="text" ng-model="item.epinNumber" ng-change="numberLengthCheck(item)" >
<clr-txt cntrlas="item" mdlval="'epinNumber'"></clr-txt>
This will create a X icon at the end of the text box and will clear the data when you click on it.
The issue is, I'm triggering a function on-change , So when the X icon is clicked, the data will be cleared and so ideally. the change event should be triggered. But for some reason the change event is not triggered when the data is cleared using the X directive.
The key point is to set bindToControllerand controllerAs alias.then you can access the controller function inside link function of directive.
angular.module('plunker', []);
function MainCtrl($scope) {
$scope.name = 'Test';
$scope.numberLengthCheck = function(n){
alert('change triggered '+ n);
};
}
angular.module('plunker').directive('clrTxt', function(){
return {
restrict: 'E',
controller: 'MainCtrl',
controllerAs: 'vm',
bindToController: true,
scope: {
cntrlas: '='
},
templateUrl: 'reverse_template.html',
replace: true,
link: function(scope, elem, attr, ctrls) {
scope.cleartxt = function () {
scope.cntrlas = '';
scope.numberLengthCheck(scope.cntrlas);
}
}
};
});
In ng-change the expression is not evaluated when the value change is coming from the model. If you want to listen the model $watch is useful
And here I think no need of sending extra attributes (cntrlas,mdlval) to clrTxtdirective. You can access the parent scope in directive by making scope:false which is default.
Directive JS
app.directive('clrTxt', function () {
return {
restrict: 'E',
replace: true,
template: '<button type="reset" ng-click="cleartxt()" >X</button>',
link: function (scope, elem, attrs, ctrl) {
scope.cleartxt = function () {
scope.item.epinNumber = '';
}
}
};
});
Controller JS
app.controller('MainCtrl', function($scope) {
$scope.$watch('item.epinNumber', function(newvalue,oldvalue) {
console.log('new value is ='+newvalue+ ' and old value is ='+oldvalue);
});
});
HTML
<body ng-controller="MainCtrl">
<input type="text" ng-model="item.epinNumber">
<clr-txt ></clr-txt>
{{item.epinNumber}}
</body>
Here is the working plunker LINK
I have a custom directive with children directives:
<rp-nav>
<rp-nav-item cat="1"></rp-nav-item>
<rp-nav-item cat="2"></rp-nav-item>
<rp-nav-item cat="3"></rp-nav-item>
<rp-nav-item cat="4"></rp-nav-item>
<rp-flyout></rp-flyout>
</rp-nav>
Here are the modules I have defined:
var app = angular.module('app', []);
app.directive('rpNav', function() {
return {
restrict: 'E',
controller: function($scope) {
$scope.currentItem = 'none'; //initialize currentItem
this.setCurrentItem = function(itemId) {
$scope.currentItem = itemId;
}
},
};
});
app.directive('rpNavItem', function() {
return {
restrict: 'E',
template: function(el, attrs) {
return '<p>item {{currentItem}} ' + attrs.cat;
},
require: '^rpNav',
link: function(scope, el, attrs, nav) {
el.on('click', function() {
nav.setCurrentItem(attrs.cat);
});
}
};
});
app.directive('rpFlyout', function() {
return {
restrict: 'E',
template: '<p style="background-color: lightblue">{{currentItem}}</p>'
};
});
The idea is to click in any of the items and make the rp-flyout element display information about the clicked rp-nav-item. The scope variable currentItem does change on click, but the template in rp-flyout does not update. What am I missing to achieve this goal? And, is this a "best practice" way of tackling this problem.
Here's a plunker
To expand on the comment, directives are not inherently part of the digest cycle, so you need to add scope.$apply() inside your el.click handler to trigger a digest cycle and update template bindings.
el.on('click', function() {
nav.setCurrentItem(attrs.cat);
scope.$apply();
});
I have dC directive
app.directive('dC', function($rootScope) {
return {
restrict: 'AE',
link: function(scope, element, attrs) {},
templateUrl: function(elem, attrs) {
return $rootScope.somePosiT
}
}
});
And I want to access inside of my controller as function is there anyway can I achieve it in order to change my directive location dynamically when click fired
app.controller('appCtrl', function($scope, $rootScope) {
clk: function() {
$rootScope.somePosiT = 'views/1.html'
}
})
I think you could do it using template and ng-include - rather than templateUrl. I think templateUrl is called before the scope values are available. You could try something like this:
app.directive('dC', function($rootScope) {
return {
restrict: 'AE',
link: function(scope, element, attrs) {},
template: '<div ng-include="somePosiT"></div>'
};
});
app.controller('appCtrl', function($scope, $rootScope) {
$scope.clk = {
somePosiT: "path/to/template.html"
};
});
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']));
}
}
I've seen the typical ('myContainer').select(); in Jquery. However, is there a way to select text within a .container div with Angular? I cannot find anything in the API reference and every search references the select element.
Angular does have .text() in its jQLite1.
You'd call it in a directive like:
angular.module('demo', [])
.directive('someDirective', function(){
return {
restrict: 'E',
templateUrl: 'template.html',
transclude: true,
scope: true,
link: function(scope, element, attrs) {
scope.content = {
changeText: function() {
button = element.find('button');
button.text('Nice new button')
}
}
}
}
}
)