Angularjs: custom grid component, dynamically add <br> elements - angularjs

Ok, I have made a really simple grid component. I fetch a column count attribute and add a <br> tag after the end of a row. I do that within the link function.
Her is the directive: http://pastebin.com/U4ckuKJw
grid.html just looks like this: <div class="grid" data-ng-transclude=""></div>
In my first example I have 7 <div> tags inside the grid component and want to have 3 columns. So after every third <div> I want a <br> to be added.
It looks like this and is working:
<div data-grid="" data-cols="5">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
</div>
This one is not working: http://pastebin.com/wtcgM2Hv
I think it is because of the directive ng-repeat and that the content of the grid component isn't rendered at the time the link function ist executed.
Any thoughts on how to solve this problem or how to optimise the component?

An easier approach may be to solve the problem with standard angular directives and css. For instance, if you float your cells and clear: left on those cells that start a new row, you can use ng-repeat and ng-class to accomplish this.
I created an example at: http://jsbin.com/idukaz/1
The html looks like this. Note I'm using ng-class to apply the class that formats the cell that needs to start a new row depending on the result of calling the custom columnEnd function. columnBreak is a scope variable for the number of columns you want. $index is a variable generated by ng-repeat:
<div class="table">
<div class="label"
ng-class="{'new-row': startNewRow($index, columnBreak) }"
ng-repeat="item in items">{{ item.name }} ({{ $index + 1 }})</div>
</div>
In your controller:
app.controller('Controller', ['$scope', function (scope) {
// list of grid data
scope.items = [];
// controls the number of columns
scope.columnBreak = 5;
// calculates if current cell is start of new row
scope.startNewRow = function (index, count) {
return ((index) % count) === 0;
};
}]);
In your css if you float your cells and clear left, you'll get your columns to dynamically
reformat when you change the columnBreak value.
.label {
float: left;
}
.new-row {
clear: left;
}

Ok, now I found the solution:
use angular directive to change classes of ng-repeat elements
I mixed it with Marks idea and manipulate the css classes now.
Thanks

Related

Changing the CSS of a div in AngularJS directive

I have a problem I have created a directive which is doing ng-repeat on an array of objects
---Showing the value on gui------
Now I want that if I click on any div of this repeat that particular div's background color should change
I have tried something like this
link:function(scope,element,attributes){
$(element).on('click',function(e){
$(element).addClass('A');
$(element).removeClass('B');
})
}
You can use the ng-class directive to apply classes on specific occurences, in your case in combination with the ng-click:
<div ng-repeat="item in items"
ng-class="{A: item.clicked, B: !item.clicked}"
ng-click="item.clicked = !item.clicked">
<!-- .. content -->
</div>
See this jsfiddle for example
You can try something like this, but this will need more workaround.
<div ng-click=“changeBackground($event)”></div>
// In Controller
$scope.changeBackground = function(event){
event.target.style.background = “#000”;
}
It would be better if you can submit your code.

Change the style of particular elements of an array inside ng-repeat in AngularJs

E.g
I have an array of text like $scope.array = [{text:'abc'}, {text:'pqr'}, {text:'xyz'}];
Now along with ng-repeat I want to change the colour of the text of any particular element of the array. how to achieve it?
IMO, we've multiple options to achieve that.
If you want to change single property then you can use ng-style but let say if you want to manipulate multiple properties then its preferable to use ng-class.
ng-style
The ngStyle directive allows you to set CSS style on an HTML element conditionally.
<div ng-repeat="contact in jsonContacts">
<span ng-style="{'color':($first ?'red':'blue')}">{{data.row}}</span>
</div>
ng-class
The ngClass directive allows you to dynamically set CSS classes on an HTML element by databinding an expression that represents all classes to be added.
<div ng-repeat="i in array" ng-class="{'green': $last, 'blue': $first}">
{{i.text}}
</div>
FYI,
The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.
$first boolean true if the repeated element is first in the iterator.
$middle boolean true if the repeated element is between the first and last in the iterator.
$last boolean true if the repeated element is last in the iterator.
Official documentations
ngRepeat
ngClass
ngStyle
Hope this helps you :)
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.array = [{text:'abc'}, {text:'pqr'}, {text:'xyz'}];
});
.green
{
color: green;
}
.blue
{
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<h3>ng-style used</h3>
<div ng-repeat="i in array" ng-style="{'color':($first ?'red':'blue')}">{{i.text}}</div>
<br/>
<h3>ng-class used</h3>
<div ng-repeat="i in array" ng-class="{'green': $last, 'blue': $first}">{{i.text}}</div>
</div>
</div>
</div>
You can achieve this by using directives such as ngClass or ngStyle, to apply classes or style changes conditionally to certain HTML elements.
Let's assume you're listing your $scope.array elements:
<ul>
<li ng-repeat="element in array">{{element.text}}</li>
</ul>
You could add a class called .red (that would change the text color to red) to an element if text === 'pqr', but changing the above example to:
<ul>
<li ng-repeat="element in array" ng-class="{'red': element.text === 'pqr'}">{{element.text}}</li>
</ul>
Similarly you can also use the directive ng-style to apply a style directly, avoiding new classes.
Since you're using an ngRepeat, you can also its iterator $index to apply classes/styles on more advanced cases such as first/last element, element index is odd/even, etc...
For more examples and clarifications, please check the official documentation for both directives:
https://docs.angularjs.org/api/ng/directive/ngClass
https://docs.angularjs.org/api/ng/directive/ngStyle
You can use ng-class or ng-style, even including an auxiliar function in your controller to calculate that style.
<div ng-repeat="item in array" ng-class="calculateClass(item)" ng-style="calculateStyle(item)">
<!-- more stuff -->
</div>
EDIT
For your case it could be useful depending on what logic you want to apply to do something like
$scope.calculateStyle = function(item){
var color;
// Some logic to define color
return {
'color': color
}
}

onclick on hyperlink should add a div horizontally using angularjs

My html:
<div id="contentDiv">
<div id="headerDiv" ><div id="titleDiv"> Queries</div></div>
<div id="valuesDiv" ><div id="yearDiv"> 2015</div></div>
<div id="graphDiv" ><div id="chartDiv">graph</div></div>
</div>
Like this div, I have another div but the content in the div is different.
How to add a new div horizontally when I click on hyperlink using angularjs?
How can I do this? please help me out regarding this
Looks like what you need is a two way binding with the ng-model directive. So the idea would be that you bind the new div to a variable in your scope which is initially in an empty or undefined state (for example, there are better ways). When the hyperlink is clicked it calls the function specified by an ng-click directive which will fill your bound object, which in turn will cause the new div to be rendered.
EDIT:
Based on your comments here is a simple example.
HTML page:
<div id="newDiv" ng-repeat="item in items">
<!-- Div content -->
<!-- example -->
<input type="text" ng-model="item.name">
</div>
<input type="button" ng-click="addItem()">
Controller:
$scope.items=[];
$scope.addItem = function() {
var newItem = {};
newItem.name = "new item name";
$scope.items.push(newItem);
}
What's happening here is the data for each div is stored in an array of objects. The ng-repeat directive will repeat the div for each object in the array. You can then fill the elements in the div using the object. Adding a new div is as simple as adding a new item to the array and angular will take care of the rest for you. Please note that I have not tested this example, but hopefully it's enough to point you in the right direction.
RE aligning the divs horizontally, this will be done with CSS, using the inline-block display mode. So you could give the div a class of, for example, "horizontalDiv" and add the following class to your CSS file:
.horizontalDiv {
display: inline-block;
}

AngularJS - Add DOM elements on counter++

I'm quite new to AngularJS and have read a little bit about how directives work. I'm still not quite sure about how to go about this problem though.
Here's the setup:
I have buttons on a view like so:
<div class="parent">
<button class="firstButton" type="button" ng-click="fetchData(param1, param2)"></button>
<button class="secondButton" type="button" ng-click="fetchData(param1, param2)"></button>
<button class="thirdButton" type="button" ng-click="fetchData(param1, param2)"></button>
<button class="fourthButton" type="button" ng-click="fetchData(param1, param2)"></button>
</div>
<div class="dataPanel">
<!-- This is where DIVs will be placed -->
</div>
Then in my controller I have:
// Init value of counter here
var counter = 0;
$scope.fetchData = function (param1, param2) {
// Do something with parameters here
counter++;
}
Ideal scenario would be when user clicks on firstButton, fetchData() initiates, getting data from a factory, then increments value of counter. A div would be created from counter value change. The number of divs created in the DOM would depend on counter value. Each created div is also populated with data gotten from each respective fetchData(). This goes on as user clicks on more buttons, although in my current project, I've limited the number of allowed dataSet duplicates.
End result of the HTML would then be:
<div class="dataPanel">
<div class="dataSet"> <!-- from firstButton -->
<p>{{dataFromFirstButton}}</p>
</div>
<div class="dataSet"> <!-- from secondButton -->
<p>{{dataFromSecondButton}}</p>
</div>
<div class="dataSet"> <!-- from thirdButton-->
<p>{{dataFromThirdButton}}</p>
</div>
</div>
What's the Angular way of doing this? I've read directives can pretty much do everything when it comes to DOM manipulation but have no idea on where to start when it comes to actually constructing the directive.
One way to accomplish this is to use ng-repeat directive to draw the divs based on an array, that is initially empty. You can set the html up so that a div is drawn for each object in the array, since the array is empty no div is initially drawn.
<div class="dataSet" ng-repeat="n in arrays[0]">
This div from button 1 contains: {{n.data}}
</div>
When you click on the buttons you can add an object, containing any needed data, to the array. Then a div will be drawn for the appropriate ng-repeat directive.
$scope.arrays = [ [], [], [], []];
$scope.fetchData = function (data, idx) {
$scope.arrays[idx].push({data: data});
}
See plunker here.

Is it possible to delete all scope variable of a controller? AngularJS

I am new to AngularJS and i dont know is it possible to delete all scope variables of a controller.I am using ng-controller with ng-repeat, like this.
<div ng-controller="main">
<div ng-repeat="x in list" ng-controller="test">
<input type="text" ng-model="text">
<span ng-click="remove($index)"> x </span>
<div>
</div>
JS
myapp.controller('main',function($scope){
$scope.list=[1,2,3,4]
})
myapp.controller('test',function($scope){
$scope.text="untitiled"
})
I want to remove the clicked scope.Can anyone help me or please suggest me a better way. Thanks
The question isn't very clear, but it looks like you may want to remove the item after clicking. Since you are passing into the remove function the index, you can splice it out. The DOM will autoupdate and remove that from the list:
$scope.remove = function(i) {
$scope.list.splice(i,1);
console.log($scope.list);
}
In the event you are doing something different in that you only want to hide it, you would push the index onto another array and then use something like ng-show or ng-hide.
$scope.remove2 = function(i) {
$scope.hideList.push(i);
}
$scope.shouldHide = function(i) {
return $scope.hideList.indexOf(i)!=-1;
}
<div ng-repeat="number in list2" >
{{number}}
<span ng-hide='shouldHide($index)' ng-click="remove2($index)"> x </span>
</div>
Here is a simple example of both scenarios. In real life, usually we are dealing with arrays of objects and what you might be doing is setting a property on one of the objects to hidden and controlling it that way.
Demo: http://plnkr.co/edit/G7UINKUCBJ4yZhQNtuJ2?p=info
If you actually want to remove all the keys from the scope:
function removeKeys() {
for(key in $scope) {
if (key.substr(0,1)!='$' && key!='this')
delete $scope[key];
}
}

Resources