I'm new to AngularJs and learning now, in my current assignment I need to achieve multiple things on ng-click.
To hide and show some DOM elements based on the ng-click
Change the background of the element where the ng-click is applied on, I'm trying to acheive this using a directive.
Mark-up:
<div class="catFilter f6" ng-click="showSubCat = !showSubCat;toggleDropDown()">
Choose A Genre
</div>
<div class="inactive" ng-show="showSubCat" ng-click="hideSubCat = !hideSubCat" ng-hide="!hideSubCat">
</div>
<div class="cat-drop-menu-list" ng-show="showSubCat" ng-hide="!hideSubCat">
</div>
angular directive
retailApp.directive('toggleDropDown', function() {
return function(scope, element, attrs) {
$scope.clickingCallback = function() {
element.css({'background':'url("../images/down-arrow.png") no-repeat 225px 12px;'});
};
element.bind('click', $scope.clickingCallback);
}
});
Issues:
I'm not able to see the directive being applied, i.e., when I click on choose a genre, it is hiding and showing the other two divs, but not changing the back ground.
You can do this a couple ways, with bindings or directives:
http://jsfiddle.net/abjeex75/
var app = angular.module('app', []);
app.controller('AppCtrl', function ($scope) {
$scope.show_sub_cat = false;
$scope.show = function () {
$scope.show_sub_cat = true;
}
$scope.hide = function () {
$scope.show_sub_cat = false;
}
});
app.directive('toggleBg', function () {
var directive = {
restrict: 'A',
link: link
}
return directive;
function link(scope, element, attr) {
element.on('click', function () {
element.toggleClass('red');
});
}
});
Related
I want to dynamically add ngClick to an attribute directive.
javascript
angular.module('app')
.directive('myDirective', ['$log', function ($log) {
return {
restrict: 'A', // PAY ATTENTION TO THIS LINE
compile: function (tElement) {
tElement.attr('ng-click', 'onClick()');
return function postLink(scope) {
scope.onClick = function () {
$log.debug('myDirective is clicked');
}
}
}
}
}]);
markup
<button my-directive>Click Me</button>
From the element inspector of Chrome, I can see that the ng-click attribute is added to the button.
I expect to see the text "myDirective is clicked." in the console when the button is clicked, but actually there's nothing printed. No error is raised. Anyone can help? Thanks in advance.
Rather than using link inside compile use the link function directly as shown below
link: function(scope, element, attrs) {
element.onClick(function(){
$log.debug('myDirective is clicked');
});
}
You can directly add the click handler to the element, you need not bind ng-click directive inside your directive.
Hello please try this one,
HTML:
<div ng-app="angularApp">
<div ng-controller="dirCtrl1">
<button ng-click="clickFun('clicked')">Button</button>
<button my-directive="directive">With directive</button>
</div>
</div>
JS:
.controller('dirCtrl1', function ($scope) {
$scope.clickFun = function (msg) {
console.log(msg);
};
})
.directive('myDirective', function(){
return{
restrict: 'A',
link: function(scope, ele, attr){
var eventName = attr.evetName || 'click';
var mas = attr.myDirective || 'just console';
ele.on(eventName, function(){
console.log(mas);
});
}
};
});
I'm trying to toggle a class by setting a Boolean value with ng-class. Now while using a custom directive while clicking outside of my focusing element needs to change the Boolean to false.
app.factory('collapsed', function($rootScope){
var scope = $rootScope.$new(true);
scope.isCollapsed = true
return scope;
})
app.controller('optSideNav', optSideNav);
function optSideNav(collapsed) {
var self = this;
this.isCollapsed = collapsed.isCollapsed;
}
app.directive('offFocusing', ['$document', 'collapsed', function ($document, collapsed) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
console.log(element)
function elementClick(e) {
e.stopPropagation();
scope.isCollapsed = collapsed.isCollapsed;
}
element.on('click', elementClick);
// remove event handlers when directive is destroyed
scope.$on('$destroy', function () {
element.off('click', elementClick);
});
}
};
}]);
<!--controller area -->
<navng-class="sideNav.isCollapsed ? 'opt-sideNav' : 'opt-sideNavXl'" ng-controller="optSideNav as sideNav" ng-model="sideNav.isCollapsed">
<a ng-click="sideNav.isCollapsed = !sideNav.isCollapsed""><i class="material-icons md-16">menu</i></a>
</nav>
<!--directive area-->
<section class="opt-appArea" flex layout="column" off-focusing>
</section>
How do I asynchronously obtain the value changes while click element to controller?
I'm trying to create a simple popover directive in angular but it doesn't seem to be working. I'm not sure why but the directive doesn't seem to get instantiated - I'm not even getting the console.log back:
var core = angular.module('core', []);
core.directive('popover', function(){
return {
restrict: 'A',
link: function (scope, el, attrs) {
var isTouchDevice = !!("ontouchstart" in window);
console.log(isTouchDevice);
if (isTouchDevice) {
el.bind("touchstart", function (e) {
console.log('on mobile');
});
} else {
el.bind("mouseover", function (e) {
console.log('on desktop');
});
}
}
};
});
Using it with the following html:
<div ng-app>
<div popover>hover me</div>
</div>
http://jsfiddle.net/nv8eq7n8/
You need not to wrap the script inside the document on jsfiddle (see the upper-left menu, I set it to no wrap - in <body>). Otherwise, the DOM would be loaded before the JS, and thus you get the missing module error.
And yes, as the other answer said, you need to specify the app name.
Here it is, working all fine: http://jsfiddle.net/wx8ydotr/
You missed the app's name:
<div ng-app="core">
It seems the code isn't loading, i had to change the html to:
<script>
var core = angular.module('core', []);
core.directive('popover', function() {
return {
restrict: 'A',
link: function (scope, el, attrs) {
var isTouchDevice = !!("ontouchstart" in window);
console.log(isTouchDevice);
if (isTouchDevice) {
el.bind("touchstart", function (e) {
console.log('on mobile');
});
} else {
el.bind("mouseover", function (e) {
console.log('on desktop');
});
}
}
};
});
</script>
<div ng-app="core">
<div popover>hover me</div>
</div>
I have a global variable called RecruiterDashboard.IsColdList. It is a boolean that decides rather to run one directive or another. When the page is loaded the variable is made either true or false through normal scripting.
What I want to do is allow the user to toggle through an ng-click rather to show this other directive or not, so I made an ng-click and set RecruiterDashboard.IsColdList from 'false' to 'true'. Problem is this doesn't reload the angular page and fire the controllers off. How do make the page run through the controllers again?
This is what I have so far:
$scope.showColdList = function (projId) {
RecruiterDashboard.isColdList = true;
};
I want to point out that I am not using angular routing. I am using C# MVC.
My logic looks like so:
callPanelControllers.controller('callPanelController', function($scope) {
$scope.isColdList = RecruiterDashboard.isColdList;
});
callPanelControllers.controller('incomingCall', function ($scope) {
$scope.showColdList = function () {
RecruiterDashboard.isColdList = true;
};
});
<div ng-click="showColdList()" ng-controller="incomingCall"></div>
<div ng-controller="callPanelController">
<cold-list ng-show="isColdList"></cold-list>
</div>
i had developed sort of a hack, so that the entire content inside of a given element is reloaded on change of a certain variable.
csapp.directive("csReloadOn", ["$timeout", function ($timeout) {
var getTemplate = function () {
return '<div ng-if="doRefreshPageOnModeChange"><div ng-transclude=""></div></div>';
};
var linkFunction = function (scope, element, attrs) {
scope.doRefreshPageOnModeChange = true;
scope.$watch(attrs.csReloadOn, function (newVal, oldVal) {
if (newVal === oldVal) return;
scope.doRefreshPageOnModeChange = false;
$timeout(function () { scope.doRefreshPageOnModeChange = true; }, 100);
});
};
return {
restrict: 'A',
transclude: true,
template: getTemplate,
link: linkFunction
};
}]);
you can use it like
<div cs-reload-on="{{pagemode}}">
<!-- your html here-->
</div>
so it just removes and re-renders the complete content inside of the div, so everything is reinitialized etc etc.
I'm adding the attribute ng-bind='data' to an element through a directive
myApp.directive('myDiv', function() {
return {
restrict: 'E',
link: function($scope, element, attrs) {
element.html('<div ng-bind="data">me</div>');
} }; });
function MyCtrl($scope) {
$('#click').click(function() {
$scope.data = 'change';
}); }
but the ng-bind isn't working as expected.
http://jsfiddle.net/HB7LU/3427/
To answer the main question your issue here is that if you want to include bindings in your template you need to compile the element. The syntax for that is something like:
$compile(angular.element("my html"))(scope)
In your case that actually ends up looking like:
myApp.directive('myDiv', function($compile) {
return {
restrict: 'E',
link: function(scope, element, attrs) {
// here adding the ng-bind dynamically
element.html($compile(angular.element('<div ng-bind="data">me</div>'))(scope));
}
};
});
To see it working checkout the updated fiddle here: http://jsfiddle.net/CC8BK/.
One other note is you are using jQuery's "click" event to change scope values. When working with angular you need to start by trying not to use jQuery and instead using the angular directives for whatever you can. In your case ng-click is the directive you should be using. I inserted this in your html so you could see what it would look like.
Hope this puts you on the right track. Best of luck!
As #drew_w said you have to compile element using $compile if you need to apply from link,
or else you can use template in directure like
template: '<div ng-bind="data"></div>'
I mostly prefer template
Also don't use jquery function like
$('#click').click(function() {
$scope.data = 'change';
});
instead you can use
$scope.change = function()
{
$scope.data = 'change';
}
or
ng-click="data = 'change'"
as #drew_w said
Take a look the full code
Working demo
html
<div ng-controller="MyCtrl">Hello, {{name}}!
<button id='click' ng-click="change()">click to 'change'</button>
<my-div>watch, this doesn't change!!!???</my-div>
</div>
script
var myApp = angular.module('myApp', []);
myApp.directive('myDiv', function ($compile) {
return {
restrict: 'E',
template:'<div ng-bind="data"></div>'
};
});
myApp.controller('MyCtrl', function ($scope) {
$scope.data = "me";
$scope.name = 'Superhero';
$scope.change = function () {
$scope.data = 'change';
}
});
here's a variation of the above answer using the Template property and using a click function:
myApp.directive('myDiv', function() {
return {
restrict: 'E',
template:'<div ng-bind="data"></div> me'
};
});
and on the controller:
$scope.click = function() {
$scope.data = 'change';
};
and on the View
<button ng-click="click()">click to 'change'</button>
http://jsfiddle.net/HB7LU/3446/