I know it is very simple but I wanna ask how to create div in ng-Repeat including an object proprty defines count of object.
For example i have an object like
function rowModel() {
this.id = 0;
this.columnCount = 1;
}
And I filled an array like below
$scope.Rows = [];
$scope.AddRow = function() {
var newRow = new rowModel();
newRow.id = 1;
newRow.columnCount = 3;
$scope.Rows.push(newRow);
}
I just wanna create an html template including 3 divs in each row.
This is my html and I wanna duplicate .cell div 3 times which is defined in object model
<button class="button" ng-click="AddRow()">Satır Ekle</button>
<div class="row cells{{row.columnCount}} bg-cyan" ng-repeat="row in Rows">
<div class="cell" ng-repeat="column in row.columnCount">{{row.id}}</div>
</div>
Anyone help?
Thanks
Use the following code in your controller
$scope.getNumber = function(num) {
return new Array(num);
}
And use the following in your view
<button class="button" ng-click="AddRow()">Satır Ekle</button>
<div class="row cells{{row.columnCount}} bg-cyan" ng-repeat="row in Rows">
<div class="cell" ng-repeat="column in getNumber(row.columnCount) track by $index">{{row.id}}</div>
</div>
Also if you do not want touch controller you can do this
ng-repeat="_ in ((_ = []) && (_.length=row.columnCount) && _) track by $index"
Here is the post where I found it.
i would create a filter for this
angular.module('myApp')
.filter('range', function(){
return function(n) {
var res = [];
for (var i = 0; i < n; i++) {
res.push(i);
}
return res;
};
});
After that, on the view is possible to use like this:
<div class="cell" ng-repeat="column in row.columnCount | range">{{row.id}}</div>
Related
Here is my code for show and hide div using loop,i have 9 div like
<div ng-show="div1">.......</div>
<div ng-show="div2">.......</div>
<div ng-show="div3">.......</div>
<div ng-show="div4">.......</div>
<div ng-show="div5">.......</div>
<div ng-show="div6">.......</div>
<div ng-show="div7">.......</div>
<div ng-show="div8">.......</div>
<div ng-show="div9">.......</div>
am trying to show and hide the div using loop based on the value.suppose here am giving value as 4.i mean 4 div ll be show,
var testOk='';
var testFAIL='';
$scope.tests=function(){
for(var i=1; i<=9; i++){
if(i <= 4)
{
testOk+='$scope.div'+i+'=true;';
}
else{
testFAIL +='$scope.div'+i+'=false;';
}
}
alert(testOk);
}
here testOK var contain showing div and testFail var contain hiding div,
output:-
testOK =$scope.Div1=true;$scope.Div2=true;$scope.Div3=true;$scope.Div4=true;
testFAIL =$scope.Div5=false;$scope.Div6=false;$scope.Div7=false;$scope.Div8=false;$scope.Div9=false;
how can i bind that value in div section.i hope u understand what am trying to asking.Thanks in advance.
You have a weird approach for this. I'd show/hide divs like this:
angular.module('app', []).controller('ctrl', function($scope) {
$scope.nums = []
for (var i=0; i <= 9; i++) {
$scope.nums.push(i);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<input ng-model="hideFrom" placeholder="Hide from this number onwards">
<div ng-repeat="num in nums" ng-hide="hideFrom && $index >= hideFrom">
{{num}}
</div>
</div>
I got progress bar in my table where I show how many hours has been spend on project. When I click on some tab, currentTab method is fired to get data from database and after I promise is resolved my TimeService function is fired also to calculate hours for progress bar, but when angular .css() is reached it doesnt update my progress bar at all and I dont know why since it definitely 100% working code. Is there some feature in mdTabs which prevent this?
HTML code below, I deleted plenty of stuff to make it more readable
<md-tab label="Testing" md-on-select="currentTab('Testing')">
<md-content class="md-padding">
<table id="projects-active" class="table table-bordered table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Description</th>
<th>Estimated time</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="project in projects.Data">
<td>{{project.Id}}</td>
<td>{{project.Name}}</td>
<td>{{project.Description}}</td>
<td>
<div class="progress-group">
<div class="progress sm">
<div class="progress-bar progress-bar-success progress-bar-striped" id="progress-bar-pId-{{project.Id}}">
</div>
</div>
</div>
</td>
<td>{{project.Status}}</td>
</tr>
</tbody>
</table>
<div class="box-footer clearfix">
<ul uib-pagination total-items="totalItems"
items-per-page="maxSize"
ng-model="currentPage"
max-size="maxSize"
class="pagination-sm"
boundary-links="true"
num-pages="pages"
ng-change="setPage(currentPage, 'Testing')"></ul>
</div>
</md-content>
Here is my function in TimeService modul
projectProgressArray: function (array) {
var items = array.Data;
angular.forEach(items, function (key, value) {
var id = key.Id;
var maxTime = key.EstimatedTime;
var currentTime = key.TimeSpend;
var percentageComplete = Math.round(((currentTime / maxTime) * PERCENTAGE) * 100) / 100;
if (!("#progress-bar-pId-" + id).length == 0) {
angular.element("#progress-bar-pId-" + id).css("width", percentageComplete + "%");
if (percentageComplete > 100) {
angular.element("#progress-bar-pId-" + id).removeClass("progress-bar-success");
angular.element("#progress-bar-pId-" + id).addClass("progress-bar-danger");
}
}
});
Here is my controller function where I fetch data to my data tables
var MAX_SIZE_PER_PAGE = 5;
$scope.currentPage = 1;
$scope.maxSize = MAX_SIZE_PER_PAGE;
$scope.pages = 0;
$scope.totalItems = 0;
$scope.setPage = function (pageNo, status) {
$scope.currentPage = pageNo;
$scope.projects = ProjectService.queryPaged({ pageSize: $scope.maxSize, pageNumber: $scope.currentPage, status: status });
$scope.projects.$promise.then(function (data) {
setTimeout(function () {
TimeService.projectProgressArray($scope.projects);
}, 0);
});
};
$scope.currentTab = function (status) {
$scope.projects = ProjectService.queryPaged({ pageSize: $scope.maxSize, pageNumber: 1, status: status });
$scope.projects.$promise.then(function (data) {
$scope.totalItems = data.TotalCount;
setTimeout(function () {
TimeService.projectProgressArray($scope.projects);
}, 0);
});
}
UPDATE: I added image where i copy progress bars outside of md-tab to show its working outside of md-tabs but not inside it.
So after some time of I found out that I cannot manipulate with css in Angular material using angular.element().css() method. I had to edit my TimeService method where I created array filled with information about single progress bar per project and send it back to my controller and use ng-style
to manipulate with my css inside ng-material DOM
projectProgressArray: function (array) {
var progressBarArray = [];
var items = array.Data;
angular.forEach(items, function (key, value) {
var progressBar = {
projectId: null,
percentage: null,
barClass: null
}
var id = key.Id;
var maxTime = key.EstimatedTime;
var currentTime = key.TimeSpend;
var percentageComplete = Math.round(((currentTime / maxTime) * PERCENTAGE) * 100) / 100;
progressBar.projectId = id;
progressBar.percentage = percentageComplete + "%";
if (!("#progress-bar-pId-" + id).length == 0) {
if (percentageComplete > 100) {
progressBar.barClass = "progress-bar-danger";
}
else {
progressBar.barClass = "progress-bar-success";
}
}
progressBarArray.push(progressBar);
});
return progressBarArray;
Reworked HTML binding
<div class="progress-group">
<div class="progress sm" ng-repeat="item in progressBars" ng-hide="item.projectId != project.Id">
<div ng-class="{'progress-bar-success': item.barClass == 'progress-bar-success',
'progress-bar-danger': item.barClass == 'progress-bar-danger' }"
class="progress-bar progress-bar-success progress-bar-striped" id="progress-bar-pId-{{project.Id}}"
ng-style="{'width':item.percentage}">
</div>
</div>
What I'm trying to do is to get a JSON object from a $http request, requested inside a controller, and build a directive that displays the multiple objects in the JSON object in a grid.
The problem is that when the object arrives, I have to process it in the directive's controller to be able to use it in the template, as such, when the JSON object changes, it is not reflected in the template. How can I make the directive know about a change in the object and force it to reload the template?
// The Directive code
amobile.directive('grid', function() {
return {
restrict: 'E',
scope: {
break: '=break',
source: '=source'
},
controller: function($scope) {
var source = $scope.source;
$scope.final_data = new Array(source.length);
if(source){
for(var j=0; j < source.length; ++j){
var total = Math.ceil(source[j]['Division'].length / $scope.break);
var data = new Array(total);
for (var i = 0; i < total; ++i) {
data[i] = source[j]['Division'].slice(i * $scope.break, (i + 1) * $scope.break);
}
$scope.final_data[j] = data;
}
}
},
templateUrl:'directives/grid.tpl.html',
replace: true
};
});
//The template
<div ng-repeat="data in final_data">
<div layout="vertical" layout-sm="horizontal" layout-padding class="" ng-repeat="row in data">
<div class="" ng-repeat="item in row">
<div flex style="width:100px">
{{item.name}}
</div>
</div>
</div>
//index.html
<div ng-controller="DivisionsCtrl as div">
<material-button ng-click="div.go()" class="material-theme-red">Button</material-button>
<div ng-if="div.data.floors">
<gridy break="3" source="div.data.floors"/>
</div>
the simplest solution would be to use watch
controller: function($scope) {
processData = function () {
var source = $scope.source;
$scope.final_data = new Array(source.length);
if(source){
for(var j=0; j < source.length; ++j){
var total = Math.ceil(source[j]['Division'].length / $scope.break);
var data = new Array(total);
for (var i = 0; i < total; ++i) {
data[i] = source[j]['Division'].slice(i * $scope.break, (i + 1) * $scope.break);
}
$scope.final_data[j] = data;
}
}
}
$scope.$watch('div.data.floors', processData, true)
},
Goal: Give the user the ability to adjust mapping results.
I am running into an issue where I need to actually change the instance used of a data bound element. Disclaimer: My json data structure may be off and I am open to possible modifications. I am coding a table header mapping app so a user can verify that the headings mapped by the server are correct. The user will have the ability to map the headers if there is an issue. I have not been able to figure out how to actually update the data bound to the result when the select menu is changed. It feels like it should be super easy. I keep finding myself with basically a finished knockout app less the last step...
Markup Snippet:
<div id="wrapper" data-bind="foreach: headings">
<h1>Bind from this</h1>
<select data-bind="value: selectMenuIdVal, event: { change: updateListing }">
<option> </option>
<!-- ko foreach: $root.headings -->
<option data-bind="value: $data.CC_FIELD_ID, visible: $data.VENDOR_FIELD_NAME(), text: $data.VENDOR_FIELD_NAME"></option>
<!-- /ko -->
</select>
<h1>To this</h1>
<ul data-bind="foreach: listingFields">
<li data-bind="text: $data.VALUE"></li>
</ul>
</div>
KO Snippet:
var Heading = function(data) {
var self = this;
var heading = ko.mapping.fromJS(data, {}, this);
heading.selectMenuIdVal = ko.observable(heading.CC_FIELD_ID());
// heading.listingFields gets mapped by the mapping plugin
this.updateListing = function(ko_evt, js_evt) {
//TODO
// Get the listing results from the value of the select menu
// self.listingFields(those listings);
}
return heading;
}
Here is my fiddle: http://jsfiddle.net/breck421/SLT9B/1/
I really not sure if undertood you right.
Please let me know if this is what you are looking for :
this.updateListing = function (ko_evt, js_evt) {
console.log("fired");
//Do something freaking awesome!!!!!!!
if (vm.dataRepo) {
for (var i = 0; i < vm.dataRepo.HEADINGS.length; i++) {
if (vm.dataRepo.HEADINGS[i].CC_FIELD_ID == heading.selectMenuIdVal()) {
var listingFields = [];
for (var j = 0; j < vm.dataRepo.LISTINGS.length; j++) {
var listing = vm.dataRepo.LISTINGS[j];
var field = listing[i];
if (field) {
listingFields.push(field);
}
}
heading.listingFields(listingFields);
// heading.listingFields = listingFields;
}
}
}
}
See fiddle
I hope it helps.
I am trying to figure out how to dynamically create bootstrap row divs with a class of row-fluid with angular.js using the ng-repeat directive.
Here is the angular:
<div ng-repeat="task in tasks" class="row-fluid">
<div class="span6 well">{{task.name}}</div>
</div>
This does not work though. The bootstrap html I wish to generate is:
http://jsfiddle.net/YKkXA/2/
Basically I need to do mod 2 of the index inside of the ng-repeat, and if its 0, close out the </div> and create a new <div class="row-fluid">. How is this possible?
The idea is to filter your items in order to group them, and make a second ngRepeat to iterate on sub-items.
First, add that filter to your module :
module.filter('groupBy', function() {
return function(items, groupedBy) {
if (items) {
var finalItems = [],
thisGroup;
for (var i = 0; i < items.length; i++) {
if (!thisGroup) {
thisGroup = [];
}
thisGroup.push(items[i]);
if (((i+1) % groupedBy) === 0) {
finalItems.push(thisGroup);
thisGroup = null;
}
}
if (thisGroup) {
finalItems.push(thisGroup);
}
return finalItems;
}
};
});
In your controler (because if you filter directly in your template, then you will have a $digest loop):
function TaskCtrl() {
$scope.tasksGroupBy2 = $filter('groupBy')(taskGroup, 2);
}
And in your .html :
<div ng-repeat="taskGroup in tasksGroupBy2" class="row-fluid">
<div ng-repeat="task in taskGroup" class="span6 well">{{task.name}}</div>
</div>
As an improvement to the answer Anthony gave, I would say that you could save yourself a lot of trouble using the slice method instead of going through all those conditions.
Try defining your filter as it follows:
module.filter('group', function() {
return function(items, groupItems) {
if (items) {
var newArray = [];
for (var i = 0; i < items.length; i+=groupItems) {
if (i + groupItems > items.length) {
newArray.push(items.slice(i));
} else {
newArray.push(items.slice(i, i + groupItems));
}
}
return newArray;
}
};
});
After that you can call the filter on your controller as Anthony pointed out in his response:
function Controller ($scope) {
$scope.itemsGrouped = $filter('group')(itemsArray, 5);
}
Off Topic: using bootstrap you can just place divs of class="span6 well" into one bigass row as they will stack nicely. (You will get an responsive layout too). Sorry if it was just an example of the behaviour that bootstrap can't handle. Anthony and Remigio are right; you have to create an extra module vehicle that will generate divs immersed into your ng-repeated tags.