AngularJS hide any parent div using ng-click in a child element - angularjs

I already know about ng-if and ng-show methods of showing/hiding DOM elements. In this case, however, I have about 100 div elements, each with multiple child span elements, and whenever a span is clicked, I want the parent div to hide.
Example:
<div>Display text
<span ng-click="hideThisDiv(this)">Option1</span>
<span ng-click="hideThisDiv(this)">Option2</span>
<span ng-click="hideThisDiv(this)">Option3</span>
</div>
In the function, I want to be able to do something like:
$scope.hideThisDiv = function(element){
element.$parent.$id.visible = false;
}
Using console.log(element.$parent) in this function shows, however, that there isn't a simple way to access a "visible" property of this div element. At least, not that I can see so far.
This seems like a simple concept, I'm just lacking the proper syntax or access method.

Try below code it works
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.hideParent = function (event) {
var pEle = event.currentTarget.parentElement;
pEle.style.visibility = "hidden";
}
});
<!DOCTYPE html>
<html ng-app="myApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-controller="MainCtrl">
<div>
This is parent div click below to hide <br />
<span ng-click="hideParent($event)">Click here to hide</span> <br />
<span ng-click="hideParent($event)">or Here</span><br />
<span ng-click="hideParent($event)">or Here</span>
</div>
</body>
</html>

If you prefer to do this with jquery then use the jqLite approach with angular.element like this:
$scope.hideThisDiv = function(el) {
angular.element(el.target).parent().addClass('hidden');
};
Then pass in the event like this:
<span ng-click="hideThisDiv($event)">Option1</span>
The add this to your css
.hidden {
display:none
}

Solution:
The better approach is to create a custom directive and hide the parent element using jqLite.
var app = angular.module('app', []);
app.directive('hideParentOnClick', function () {
return {
link: function (scope, element) {
element.on('click', function () {
element.parent().css({display: 'none'});
});
}
}
});
And in your HTML:
<div>
Display text
<span hide-parent-on-click>Option1</span>
<span hide-parent-on-click>Option2</span>
<span hide-parent-on-click>Option3</span>
</div>
Plunker Example
Advantages:
You can combine this directive with the aforementioned ng-click because the last one is not utilized in this method and can be freely used for any other purpose.
Directives are intended for DOM manipulations, not controllers. Read more here.
Better overall modularity.

Related

Allow only one collapse div in ng-repeat

I have some data in the ng repeat, and inside that I have some data under each divs which is collapsed.
No when I click on the main div, I want only one div to collapse in at a time.
Eg: if I click abc, asdasd should be displayed.. Then if I click abc1, asdasd1 should be displayed but NOT asdasd
<script>
angular.module('myApp', [])
.controller("Ctrl_List", ["$scope", function(s) {
s.people = [
{name:"Sten", age:"49"}
,{name:"John", age:"39"}
,{name:"Hanne", age:"37"}
,{name:"Jens", age:"37"}
,{name:"Brian", age:"24"}
,{name:"Johnny", age:"24"}
,{name:"Peter", age:"49"}
]
s.obj = [
{
"name":'abc',
"text":'asdasd'
},
{
"name":'abc1',
"text":'asdasd1'
}
]
}])
html:
<body ng-app="myApp" ng-controller="Ctrl_List">
<div ng-repeat="ob in obj">
<button class="btn" data-toggle="collapse" href="#abc-{{ob.name}}"> {{ob.name}}</button>
<div id="abc-{{ob.name}}" class="collapse">{{ob.text}}</div>
</div>
</body>
data-parent is not working for me, or may be I am not using it properly.
Please Check the Fiddle here
Using a pure Angular approach rather than using JQuery for this.
Add a new property show to the each object and use ng-if to show/hide its corresponding text using a method in controller.
<div ng-repeat="ob in obj">
<button class="btn" ng-click=" showThis(ob)"> {{ob.name}}</button>
<div ng-if="ob.show">{{ob.text}}</div>
</div>
controller method
s.showThis = function(obj) {
//Hides all
angular.forEach(s.obj, function(ob) {
if(ob.name != obj.name) {
ob.show = false;
}
});
//Toggles current object show/hide
obj.show = !obj.show;
}
Working Fiddle

angularjs dom manipulation based on button click

basically i want to change the attribute value based on the button i clicked,
these are the two buttons
<button ng-click="fn(a)"></button>
<button ng-click="fn(b)"></button>
and then i have a prebuilt directive who takes value as input,
<div directive-name="" id="abc"></div>
if i click on first button,i want the value of directive based on button clicked.
What i did earlier;
$scope.go = function(data){
if(data==a){
var b = document.querySelector( 'div' );
b.setAttribute("directive-name","value");
}
else{}
}
here the problem is that it is selecting the first div of document and setting attribute value for that.
I also tried to pass it with id like
var b = angular.element(document.querySelector('#abc'));
I also saw some custom directives to do so, but they are not working
AngularJS DOM Manipulation through Directives
If possible provide me a demo in plunkr or fiddle
and also if i want to change css property of div based on button clicked
Thanks in advance
You can do it like this.
Assign the directive-name value to a $scope.variable and then use variable as the value in HTML.
HTML - 1:
<button ng-click="go(a)"></button>
<button ng-click="go(b)"></button>
HTML - 2:
<div directive-name="{{directive}}" id="abc"></div>
JS:
$scope.go = function(data){
if(data==a){
$scope.directive = "directive-1";
}else if(data==b){
$scope.directive = "directive-2";
}
}
To assign class name to div you can define other $scope.classVar and then use that in HTML like below:
<div directive-name="{{directive}}" id="abc" ng-class="classVar"></div>
I hope this will solve your problem.
This should work, (you had some errors in your code):-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.fn = function(data,id) {
if (data == 'a') {
var b = document.querySelector('#'+id);
b.setAttribute("directive-name", "value");
} else {
}
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div directive-name="" id="abc"></div>
<button ng-click="fn('a','abc')">A</button>
</div>
"Basically I want to change the attribute value based on the button I clicked."
You can do this by changing the attribute value the angular way, referencing a property of $scope or the controller instance in your template. When clicking a button, set the variable to the value you require to be passed to your directive.
Note: When you pass a value into your ngClick directive, you need to pass it as a string unless a and b are declared as properties of $scope.
Here's a basic example:
// app.js
(function() {
'use strict';
angular.module('app', []);
})();
// main.controller.js
(function() {
'use strict';
angular.module('app').controller('MainController', MainController);
MainController.$inject = ['$scope'];
function MainController($scope) {
$scope.fn = fn;
function fn(data) {
// set the value so it's accessable in the view
// therefore we can pass it into our directive
$scope.myVar = data;
}
}
})();
// directive-name.directive.js
(function() {
'use strict';
angular.module('app').directive('directiveName', directiveNameDirective);
function directiveNameDirective() {
return {
restrict: 'A',
scope: {
directiveName: '='
},
template: '<span>directiveName: {{ directiveName }}</span>'
};
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainController as MainCtrl">
<!-- here we pass a and b as strings otherwise they get evaluated as variables -->
<button ng-click="fn('a')">Set a</button>
<button ng-click="fn('b')">Set b</button>
<hr>
<!-- here we pass myVar which is declared as a property of $scope when the fn function is called -->
<div directive-name="myVar" id="abc"></div>
<hr> myVar: {{ myVar }}
</div>
</div>

How to make Angular bind blank inputs to a model?

Here is a simple Angular example:
<!DOCTYPE html>
<html ng-app="GenericFormApp">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
</head>
<body ng-controller="GenericFormCtrl as ctrl">
<div>
Model: {{ctrl.model}}
</div>
<div>
<input ng-model="ctrl.model" />
</div>
<div>
<input type="button" value="Alert model" ng-click="ctrl.showModel();" />
</div>
<script>
angular.module("GenericFormApp", [])
.controller("GenericFormCtrl", [function () {
this.showModel = function () { alert(this.model); };
}])
</script>
</body>
</html>
The above shows how to bind an input to a model, a fundamental feature of Angular.
It also allows the user to pop up a modal dialog with the contents of the input. This works fine except when the input is left blank.
In that case, it displays "undefined".
I could, of course, simply write a line of code that sets the initial value of the model to a blank string, but this is not particularly practical because in my real application, there are many inputs, and the user may leave any number of them blank.
In short, I want to know how to make it so that Angular knows that a blank input should contain a blank string in the model.
I would go with custom directive to extend default input directive behaviour. So in case if input has a model this directive would check if this model is undefined and if so assign it an empty string value.
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<div ng-app="GenericFormApp" ng-controller="GenericFormCtrl as ctrl">
<input ng-model="ctrl.model" /> {{ctrl.model}}<br>
<input type="button" value="Alert model" ng-click="ctrl.showModel();" />
<script>
angular.module("GenericFormApp", [])
.controller("GenericFormCtrl", [function () {
this.showModel = function () { alert(this.model); };
}])
.directive("input", function($parse) {
return {
link: function(scope, element, attr, ngModelController) {
if (attr.ngModel) {
var model = $parse(attr.ngModel);
if (typeof model(scope) === 'undefined') {
model.assign(scope, '');
}
}
}
};
});
</script>
</div>
I igree with #Claies, but, if you need this for some specific attributes, you can use ng-init:
<input type="text" ng-init="ctrl.model = ctrl.model || ''" ng-model="ctrl.model"/>
or create a specific directive, like 'auto-init' or similar, not directly on input element.

how to set visibility to a class with angular.js

using angular.js is there a way to set the visibility of all the elements in the page with a specific class using a single model variable?
the angular equivalent of
$(".myClass").hide();
thanks,
Luca
In html code you can use directive
<div ng-show="shouldShow"></div>
and in controller
$scope.shouldShow = (true or flase)
Try ngClass
Take a look at this.
Here depends upon the Boolean value of $scope.data the content will be shown or hidden.
i.e if $scope.data = true content will be hidden, and if false content will be shown
Working Demo
Html
<div ng-app='myApp' ng-controller="ArrayController">
<div ng-class="{show: data, hide:data}">Content</div>
</div>
Script
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.data = true;// for Hiding
});
CSS
.hide{
display:none;
}
I would say to add a directive like this.
directive('className', function () {
return {
restrict: 'C',
link: function (scope, elem, attrs) {
elem.hide();
}
}
});
In MarkUp
<div class="className">Content</div>
Here is an Plunker, made for you.
I think this can be useful to you.Have a look at this jsfiddle
Html
<div ng-app=''>
<div ng-class="selectCss">Content</div>
<input type="button" ng-model="selectCss" value="show" ng-click="selectCss='show'">
<input type="button" ng-model="selectCss" value="hide" ng-click="selectCss='hide'"/>
</div>
Css
.hide{
display:none;
}

How to set repeated element id in AngularJS?

I'd like to do something like:
<div class='row' ng-repeat='row in _.range(0,12)'>
<div id='{{row}}'></div>
</div>
but when in the controller I try:
function SetterForCatanCtrl($scope) {
$scope._ = _;
try {
var tile = document.getElementById('5');
tile.style.backgroundImage = "url('aoeu.png')";
} catch (e) {
alert(e)
}
}
getElementById returns null so how can an element's id be set using AngularJS variables?
The function SetterForCatanCtrl is run only once, when angular encounters a ngController directive while it bootstraps your app. When this happens the element you want to access from the DOM doesn't exist yet.
Doing DOM manipulation from a controller is not a good practice, directives are can solve the kind of problem you are facing. Your use case can be solved with CSS and just switching classes but I guess you want to do more than just setting a background image.
DOM manipulation from a controller
You are not asking for custom directives, so a quick solution could done using the ngClick directive and call a method that can switch images
Example HTML
<div ng-controller='ctrl'>
<div class='row' ng-repeat='row in _.range(0,12)'>
<div id='{{row}}' ng-click="click($index)">
<button>{{row}}</button>
</div>
</div>
</div>
And JS
var App = angular.module('app', []);
App.run(function($rootScope) {
$rootScope._ = _;
});
App.controller('ctrl', function($scope){
$scope.click = function(idx){
var elem = document.getElementById(idx);
console.log('clicked row', idx, elem);
};
​}); ​
So when a button is clicked you will get an id and use it to get an element from the DOM. But let me repeat, a for this use case a directive is a better choice.
JSFiddle: http://jsfiddle.net/jaimem/3Cm2Y/
pd: if you load jQuery you can use angular.element(<selector>) to select elements from the DOM.
edit: adding directive example
DOM manipulation from a directive
Using a directive is simpler, since you can just bind an event to the element the directive is applied to
HTML
<h1>Directive</h1>
<div class='row' ng-repeat='row in _.range(0,12)'>
<div id='{{row}}' my-directive>
<button>{{row}}</button>
</div>
</div>
JS
App.directive('myDirective', function(){
return function(scope, element, attr){
element.bind('click', function(){
console.log('clicked element: ', element, element.html());
});
};
});
http://jsfiddle.net/jaimem/3Cm2Y/1/

Resources