How do i select sibling Elements in AngularJS - angularjs

I got a 4-5 rows of div ... when i click on any row it should change the selected one and color it as red and rest all to black ... i am using below logic but not working for me giving error as angular.min.js:117 TypeError: angular.element(...).siblings is not a function
Do i need to include jQuery file?
Can i do it without including jQuery file?
plz help
$scope.divClick = function($event){
console.log($event.target);
/* below siblings function not working for me*/
angular.element(event.target).siblings().css('color','black');
angular.element(event.target).css('color','red');
};
<div ng-controller="homeController">
<h1>Welcome</h1>
<div ng-repeat="x in json" ng-click="divClick($event)">
Name: {{x.Name}}<br/> City: {{x.City}}<br/> Country: {{x.Country}}<br/><br/>
</div>
</div>

Set your default color to be black.
<div ng-repeat="x in json" ng-class="{setRed: $index == value}" ng-click="divClick($index)">
Give CSS style to your class setRed.
Your controller function:
$scope.divClick = function(index){
$scope.value = index;
};

In general it's bad idea to modify DOM right from your controllers.
It's better to use scope or model properties and make decisions what class to apply based on them.
<div ng-repeat="x in json" ng-click="select($index)" ng-class="{'selected': $index == selectedIndex}">
Name: {{x.Name}}<br/>
City: {{x.City}}
Then you just have to update selectedIndex in you click handler
$scope.select = function(x) {
$scope.selectedIndex = x;
};
Fully working solution is here
https://jsfiddle.net/kvtcw8y6/4/
Other way is to have isSelected property on you model and update it accordingly.

Related

How do I reference and set all scope variables created from ng-click within ng-repeat?

I want to be able to hide the item.value when I click on item.label or just hide everything with I click on the button. I'm not too sure how the "hide" variables are related here. From what I understand, they are created separately in an isolated scope so my button should not work. What is the solution here?
<button ng-click="hide=false">HideAll</button>
<div ng-repeat="item in items">
<div ng-click="hide=!hide">item.label</div>
<div ng-hide="hide">item.value</div>
</div>
You should be using the dot syntax and within each item model, you can use your toggle button to toggle the hide property of each individual item. This way you can ng-hide each item via item.hide expression.
Angular's ng-hide directive creates a watch on the expression. When the value of the evaluated expression changes, it triggers a change to the DOM to show (if the value is falsey) or hide (if the value is not falsey). Initially, the items array does not have the hide property set, so they are all undefined, which evaluates to a falsey value, thus the items do not hide by default on initial display. Once an item's hide property is set (either by using the ng-click expression to execute the controller's toggleHide method or the controller's hideAll method).
These are some of the basics of angular expressions and core ng directives.
angular.module('myApp', [])
.controller('MainController', function () {
this.$onInit = function $onInit() {
this.items = [
{value: 'Item 1'},
{value: 'Item 2'},
{value: 'Item 3'}
];
};
this.toggleHide = function toggleHide(item) {
item.hide = !item.hide;
};
this.hideAll = function hideAll() {
var items = this.items;
for (var i = 0; i < items.length; ++i) {
items[i].hide = true;
}
};
});
<script src="//code.angularjs.org/1.6.5/angular.js"></script>
<div ng-app="myApp" ng-controller="MainController as mc">
<button ng-click="mc.hideAll()">Hide All</button>
<div ng-repeat="item in mc.items">
<div><button ng-click="mc.toggleHide(item)">Toggle</button></div>
<div ng-hide="item.hide">{{::item.value}}</div>
</div>
</div>
This answer is leveraging some features of the more recent versions of angular 1.x (controller lifecycle methods and one time binding -- none of which are shipped with the stackoverflow snippet of Angular 1.2).

How can I check in an angular view if an object's property is an object itself?

I'm building some form views with angular and need to run over some nested objects.
I've run into an issue and can't figure out exactly what I'm missing.
<div ng-app="app">
<div ng-controller="Main">
<div ng-repeat="(key, value) in ob">
{{key}}
<div ng-if="angular.isObject(ob[key])">
angular.isObject() returns true!
</div>
<div ng-if="!angular.isObject(ob[key])">
angular.isObject() returns false!
</div>
<div ng-if="typeof(ob[key]) === 'object'">
typeof is object!
</div>
<div ng-if="typeof(ob[key]) !== 'object'">
typeof is not object!
</div>
</div>
</div>
</div>
In controller:
$scope.ob = {
prop1: 1,
prop2: 'asd',
prop3: {
subprop1: 'one',
subprop2: 'two'
}
};
In the code above I'm trying to use angular.isObject to detect whether the property is an object, so I can go into another loop afterwards. Both ng-ifs resolve to false, even if my third property is an object. Same while using typeof.
Codepen link: http://codepen.io/anon/pen/rLEVLr
You can't use angular in template. Template is evaluated against scope object, not global one (e.g. window, which has angular property as global variable).
If you really want to you can simply expose reference to the angular like this:
$scope.angular = angular
Demo: http://codepen.io/anon/pen/yJdNzV?editors=1010
But better approach is to expose only function that you actually need:
$scope.isObject = angular.isObject
and use it in template like this:
ng-if="isObject(value)"

Change the style of the selected ng-repeat item and remove the other item's style

I'm a freshman to AngularJS. I try to modify the item's style using AngularJS, but I meet this bug:
when I select another item, the background of the first item is still blue. How to change my code to fix this?
Here is my plnkr.
And here is the code.
<div ng-init="selectedNode = false">
<div ng-repeat="item in items" ng-click="selectedNode=true" ng-class="{selected: selectedNode == true}">{{item.value}}</div>
</div>
When I click on 2 after click on 1, the background color of 1 should be removed. It means only one item should be selected. How to slove this problem?
The problem is subtle -- ng-repeat creates a new isolated scope for each of its entries. So when your click handler sets selectNode to true, it happens on its own scope, and not its parent.
Easily remedied. (I surrounded your example with some mock data -- I'm sure you have your own):
<div ng-app ng-init="items = [{value: 'red'},
{value: 'green'},{value: 'blue'},{value: 'yellow'},
{value: 'orange'}]">
<div ng-init="selection = { selectedNode: null }">
<div ng-repeat="item in items"
ng-click="selection.selectedNode = item"
ng-class="{selected: selection.selectedNode == item}">
{{item.value}}
</div>
</div>
</div>
https://jsfiddle.net/kfnkn827/
First, I create an object in the parent scope that can be modified by the children. Notice that instead of a boolean, I just use a reference in the parent. This relieves you from storing a bunch of flags.
Edit: I saw your Plinkr after submitting. Sorry! :-P
A couple things. Don't use ng-init to init the variable, do it in a controller. Second, ng-repeat creates a child scope, so you should make a data model for this, so data.selectedNode. Then just set the selectedNode to the currently repeated item, and then style it if the selectedNode equals the current item.
<div ng-init="data.selectedNode ={}"> <!-- do this in a controller, not ng-init -->
<div ng-repeat="item in items" ng-click="data.selectedNode=item" ng-class="{selected: data.selectedNode == item}">{{item.value}}</div>
</div>
Please try out bellow code.
if click on row, bind clicked item value in selectedNode variable and apply active-row class.
<style>
.active-row{
background-color: #D4D0D0;
}
</style>
<div ng-init="selectedNode = false">
<div ng-repeat="item in items" ng-click="selectedNode=item.value" ng-class="(selectedNode == item.value) ? 'active-row' : ''">{{item.value}}</div>
<br />
</div>

ng-init fetches value only once, even if the model value changes

I have a status filed deep nested to 3 levels in my model, I want to apply different classes to a div based on the value of the status. In order the save the typing and keep the html tidy, I wanted to apply short name to this status so I used ng-init to copy the values and use ng-class on ng-init variable. But ng-init gets its value only once, when I change the status again in controller it doesnt change but holds the old value. Is there a way to give short names to response.obj1.obj2.status at least inside a div?
<div ng-app="app">
<div ng-controller="statusCtrl">
<button ng-click="toggle()">toggle</button>
<div id="section1" ng-init="s1Status=response.section1.status">
<div id="statusIndicator" ng-class="{'success':s1Status==0,'error':s1Status==1}">Status</div>
</div>
<span>{{response.section1.status}}</span>
</div>
var app = angular.module('app', [])
app.controller('statusCtrl', function ($scope) {
$scope.response = {
section1: {
status: 1
}
};
$scope.toggle = function () {
if ($scope.response.section1.status === 0) $scope.response.section1.status = 1;
else $scope.response.section1.status = 0;
}
});
Demo: http://plnkr.co/edit/ES7rgf97BPFAWzkfIEhw?p=preview
EDIT:
Knockout JS has nice way to do this, where you can bind a model at any level to a div and any models referred inside that div will work with the parnet model as context. Thats what I'm looking for.
<div id="section1" data-bind="response.section1">
<div id="statusIndicator" data-bind=" css:{success:status==0, error:status=1 }">Status</div>
</div>

AngularJS: create element dynamically

How do I go about create an element in my controller? e.g. on a click event?
example controller:
function AddCtrl($scope){
$scope.add = function(){
// do stuff to create a new element?
}
}
example view:
<div ng-controller="AddCtrl">
<button ng-click="add()">Add</button>
// create <input type="text" ng-model="form.anotherField">
</div>
Any suggestions much appreciated.
AngularJS is intended to follow MVC - so the controller creating an element in the view doesn't agree with the MVC behavior. The controller should not know about the view.
It sounds as if you want to have a control appear based on some conditional logic. One approach would be to bind to the visibility of the element.
In Angular, your controllers should not be manipulating the DOM directly. Instead, you should describe the elements you need in your templates, and then control their display with directives, like ng-switch, ng-hide / ng-show, or ng-if, based on your model, ie, your data.
For example in your controller you might do something like:
$scope.showForm = false;
And then in your partial:
<div id="myForm" ng-show="showForm">
<!-- Form goes here -->
</div>
By switching $scope.showForm between true and false, you will see your myForm div appear and disappear.
This is a classical mistake coming from jQuery moving to Angular or any other MVC library. The way you should think is to let the view react to changes in the scope.
$scope.items = []
$scope.add = function(){
$scope.items.push({});
}
In the view:
<input type="text" ng-repeat="item in items" ng-model="item.property">
If you want to display an element based on some condition or after the click, use ng-switch: http://docs.angularjs.org/api/ng/directive/ngSwitch
If you want to add multiple elements, create a repeated list of items and add an item to your view-model on clicking the button:
$scope.yourlistofitems = [];
$scope.add = function() {
$scope.yourlistofitems.push("newitemid");
}
And in the HTML:
<input type="text" ng-repeat="item in yourlistofitems" ng-model="item.property">

Resources