I am trying to make a Dynamic table in Angular.js, in which the user inputs number of columns, in a text box provided. Then add buttons are provided under each column to add as much cells as user wants. The cell will only be added to that column only.
I am using ng-repeat to repeat the number of columns and add buttons.
I am able to get the response of the user in a variable, ie, the column under which the user wants to add the cell.
Can someone please give me a controller to add a cell to the selected column either by using ng-repeat , ng-model or without it.
my table code looks somewhat like this:
<table>
<tr>
<th ng-repeat="n in arr track by $index">SET {{n.setalpha}} </th><!--table heading, dont mind this-->
</tr>
<tr ng-repeat="<!--something goes here-->">
<!--<select ng-model="name" ng-options="options.topicname for options in topics"></select>-->
</tr>
<tr>
<td ng-repeat="n in arr track by $index">
<button ng-click="addSelected($index+1)">add{{$index+1}}</button>
</td>
</tr>
</table>
where: n in arr track by $index , is used to repeat the table heading and add button say 'n' number of times and addSelected($index+1) is a function whose controller is:
$scope.addSelected = function (setno) {
console.log(setno);
$scope.thisset = setno;
}
, $scope.thisset is the variable in which i have the response of the user, ie, the column under which the user wants to add a cell.
NOTE: I want to add the cell in column only under which the user wants. NOT in all columns. MY CODE:
var app = angular.module('topicSelector', []);
app.controller('topicController', function ($scope) {
$scope.arr = [];
$scope.thisset = -1; //tells in which set, cell has to added.
$scope.topics = [
{
topicid: "1",
topicname: "history"
},
{
topicid: "2",
topicname: "geography"
},
{
topicid: "3",
topicname: "maths"
}
];
$scope.DefineSets = function () {
for (var i = 1; i <= $scope.no_of_sets; i++) {
$scope.arr.push({
setno: i,
setalpha: String.fromCharCode(64 + i)
});
};
};
$scope.addSelected = function (setno) {
console.log(setno);
$scope.thisset = setno;
}
});
table {
width: 100%;
}
<!doctype html>
<html ng-app="topicSelector">
<head>
<title>
topic selector
</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h3>Enter number of sets:</h3>
<div ng-controller="topicController">
<form ng-submit="DefineSets()">
<input type="text" ng-model="no_of_sets" placeholder="number of sets" name="no_of_sets">
<button>Submit</button>
</form>
<br>
<br>
<table>
<tr>
<th ng-repeat="n in arr track by $index">SET {{n.setalpha}} </th>
</tr>
<!--<tr ng-repeat="">
<select ng-model="name" ng-options="options.topicname for options in topics"></select>
</tr>-->
<tr>
<td ng-repeat="n in arr track by $index">
<button ng-click="addSelected($index+1)">add{{$index+1}}</button>
</td>
</tr>
</table>
</div>
</body>
</html>
LINK TO PLUNK PLUNK
In the following example I used lists instead of tables with fle display, IMHO it is a better approach:
(function (angular) {
"use strict";
function GrowController ($log) {
var vm = this;
vm.cols = [];
vm.size = 0;
vm.sizeChanged = function () {
var size = vm.size, cols = vm.cols,
diff = size - cols.length;
$log.debug("Size changed to", size, cols);
if (diff > 0) {
for (var i = 0; i < diff; i++) {
cols.push([]);
}
} else {
cols.splice(diff, -diff);
}
};
vm.addCell = function (index) {
var cols = vm.cols;
$log.debug("Cell added in column", index);
cols[index].push(index + "." + cols[index].length);
};
}
angular.module("app",[])
.controller("GrowController", ["$log", GrowController]);
}(angular));
ul {
list-style: none;
padding: 0;
margin: 0;
}
.cols {
display: flex;
}
.cells {
display: flex;
flex-direction: column;
}
button.add-cell {
display: block;
}
<div ng-controller="GrowController as $ctrl" ng-app="app" ng-strict-di>
<p>
<label for="size">Number of columns(0-10):</label>
<input id="size" type="number" ng-model="$ctrl.size" ng-change="$ctrl.sizeChanged()" min="0" max="10">
</p>
<ul class="cols" ng-if="$ctrl.cols.length">
<li ng-repeat="col in $ctrl.cols">
<button class="add-cell-button" ng-click="$ctrl.addCell($index)">Add cell</button>
<ul class="cells" ng-if="col.length">
<li ng-repeat="cell in col">{{ ::cell }}</li>
</ul>
</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
Anyway, I Angularjs 1.5.6 you should consider using "Components" instead of "Controllers" and "one-side" bindings.
Related
I have an add button which adds the row containing texbox. However I want to remove the row of the table by clicking the respective remove button.
The view page code is like this:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>showintable</title>
<script src="~/scripts/jquery-3.1.1.min.js"></script>
<script src="~/scripts/angular.min.js"></script>
<script src="~/scripts/angular-messages.min.js"></script>
<script src="~/app/controller/checkCtrl.js"></script>
<script src="~/app/filter/filterrange.js"></script>
</head>
<body ng-app="app">
<div ng-controller="sayCtrl">
<table border="1">
<tr>
<th>S. No.</th>
<th>Textbox1</th>
<th>Texbox2</th>
</tr>
<tr ng-repeat="v in [] | range:tellrange">
<td>{{$index+1}}</td>
<td><input type="text" ng-model="Namemodel[$index]" /></td>
<td><input type="text" ng-model="Addressmodel[$index]" /></td>
<td><input type="button" ng-click="subtractrow()" value="Remove" /></td>
</tr>
<tr><td align="right" colspan="4"><input ng-click="addrow()" type="button" value="Add" /></td></tr>
</table>
</div>
</body>
</html>
The controller checkCtrl.js of angularjs is like this:
angular.module('app', ['ngMessages']).controller('sayCtrl', SayController);
SayController.$inject = ['$scope', '$http'];
function SayController($scope, $http) {
$scope.Namemodel = [];
$scope.Addressmodel = [];
$scope.tellrange = 1;
$scope.addrow = function () {
$scope.tellrange = $scope.tellrange + 1;
};
$scope.subtractrow = function () {
};
}
The filter filterrange.js of angularjs is like this:
angular.module('app').filter('range', function () {
return function (input, total) {
total = parseInt(total);
for (var i = 0; i < total; i++) {
input.push(i);
}
return input;
};
});
The page looks like this:
https://drive.google.com/open?id=0B8ZNi-QTxOOYUjNqcnlraDVydVE
I have searched for it but I could not get the relevant answer. Any help is appreciated.
Thanks in advance..............
First, make it easier to iterate through the rows. You want N rows, and each row should have two pieces of information: a name and an address.
So don't use two arrays. Use one array, of rows, where each row has a name and an address:
$scope.rows = [
{
name: 'name 1',
address: 'address 1'
},
{
name: 'name 2',
address: 'address 2'
}
];
To add a row, all you need is
$scope.rows.push({
name: '',
address: ''
});
To iterate on the rows, all you need is
<tr ng-repeat="row in rows">
<td>{{$index+1}}</td>
<td><input type="text" ng-model="row.name" /></td>
<td><input type="text" ng-model="row.address" /></td>
<td><input type="button" ng-click="removeRow(row)" value="Remove" /></td>
</tr>
As you see, you need to pass what row to remove in your removeRow function.
And to remove the row, all you need is to find its index in $scope.rows, and remove that index:
$scope.removeRow = function(row) {
var index = $scope.rows.indexOf(row);
$scope.rows.splice(index, 1);
}
I don't know exactly what each row is supposed to represent. I guess it might be a user, for example, so feel free to rename rows to users, and row to user. Naming things, and having a good, correct model, is the key. Your page displays a table of users. Not two tables of names and addresses.
I have an add button which adds the row containing texbox. However I want to remove the row of the table by clicking the respective remove button.
The view page code is like this:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>showintable</title>
<script src="~/scripts/jquery-3.1.1.min.js"></script>
<script src="~/scripts/angular.min.js"></script>
<script src="~/scripts/angular-messages.min.js"></script>
<script src="~/app/controller/checkCtrl.js"></script>
<script src="~/app/filter/filterrange.js"></script>
</head>
<body ng-app="app">
<div ng-controller="sayCtrl">
<table border="1">
<tr>
<th>S. No.</th>
<th>Textbox1</th>
<th>Texbox2</th>
</tr>
<tr ng-repeat="v in [] | range:tellrange">
<td>{{$index+1}}</td>
<td><input type="text" ng-model="Namemodel[$index]" /></td>
<td><input type="text" ng-model="Addressmodel[$index]" /></td>
<td><input type="button" ng-click="subtractrow()" value="Remove" /></td>
</tr>
<tr><td align="right" colspan="4"><input ng-click="addrow()" type="button" value="Add" /></td></tr>
</table>
</div>
</body>
</html>
The controller checkCtrl.js of angularjs is like this:
angular.module('app', ['ngMessages']).controller('sayCtrl', SayController);
SayController.$inject = ['$scope', '$http'];
function SayController($scope, $http) {
$scope.Namemodel = [];
$scope.Addressmodel = [];
$scope.tellrange = 1;
$scope.addrow = function () {
$scope.tellrange = $scope.tellrange + 1;
};
$scope.subtractrow = function () {
};
}
The filter filterrange.js of angularjs is like this:
angular.module('app').filter('range', function () {
return function (input, total) {
total = parseInt(total);
for (var i = 0; i < total; i++) {
input.push(i);
}
return input;
};
});
The page looks like this:
https://drive.google.com/open?id=0B8ZNi-QTxOOYUjNqcnlraDVydVE
I have searched for it but I could not get the relevant answer. Any help is appreciated.
Thanks in advance..............
First, make it easier to iterate through the rows. You want N rows, and each row should have two pieces of information: a name and an address.
So don't use two arrays. Use one array, of rows, where each row has a name and an address:
$scope.rows = [
{
name: 'name 1',
address: 'address 1'
},
{
name: 'name 2',
address: 'address 2'
}
];
To add a row, all you need is
$scope.rows.push({
name: '',
address: ''
});
To iterate on the rows, all you need is
<tr ng-repeat="row in rows">
<td>{{$index+1}}</td>
<td><input type="text" ng-model="row.name" /></td>
<td><input type="text" ng-model="row.address" /></td>
<td><input type="button" ng-click="removeRow(row)" value="Remove" /></td>
</tr>
As you see, you need to pass what row to remove in your removeRow function.
And to remove the row, all you need is to find its index in $scope.rows, and remove that index:
$scope.removeRow = function(row) {
var index = $scope.rows.indexOf(row);
$scope.rows.splice(index, 1);
}
I don't know exactly what each row is supposed to represent. I guess it might be a user, for example, so feel free to rename rows to users, and row to user. Naming things, and having a good, correct model, is the key. Your page displays a table of users. Not two tables of names and addresses.
I 'm working on my AngularFire project. I've a database something like this https://dinosaur-facts.firebaseio.com/. What I'm doing is first searching the key like the dinosaurs child such as "linhenykus" and storing its keys and values to other $scope variable.
my code in controller
var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs" + "/" + $scope.dinoID); //$scope.dinoID is variable containg dino keys
$scope.detRef = $firebaseArray(ref);
I'm getting the output like
[{"$value":-85000000,"$id":"appeared","$priority":null},{"$value":0.6,"$id":"height","$priority":null},{"$value":1,"$id":"length","$priority":null},{"$value":"theropoda","$id":"order","$priority":null},{"$value":-75000000,"$id":"vanished","$priority":null},{"$value":3,"$id":"weight","$priority":null}]
How to fetch the keys and values?
Use ngRepeat directive, as below:
<tr ng-repeat="obj in array track by $index">
To filter the array you can use the filter of Angular:
<tr ng-repeat="obj in array | filter: criteria track by $index">
Here's an example:
(function() {
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', '$filter'];
function MainCtrl($scope, $filter) {
$scope.criteria = {};
$scope.array = [
{
"$value":-85000000,
"$id":"appeared",
"$priority":null
},
{
"$value":0.6,
"$id":"height",
"$priority":null
},
{
"$value":1,
"$id":"length",
"$priority":null
},
{
"$value":"theropoda",
"$id":"order",
"$priority":null
},
{
"$value":-75000000,
"$id":"vanished",
"$priority":null
},
{
"$value":3,
"$id":"weight",
"$priority":null
}
];
$scope.getObj = function(value, id) {
$scope.obj = $filter('filter')($scope.array, {
"$value": value,
"$id": id
})[0];
}
$scope.getObj("theropoda", "order");
}
})();
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<input type="text" placeholder="Search by value" ng-model="criteria.$value">
<input type="text" placeholder="Search by id" ng-model="criteria.$id">
<!-- Note that this button is just as an example to change the object displayed below -->
<button type="button" ng-click="getObj()">Change the value of object</button>
<hr>
Obj: <span ng-bind-template="Value: {{obj.$value}}, Id: {{obj.$id}}"></span>
<p></p>
<table width="100%">
<thead>
<tr>
<th>Value</th>
<th>Id</th>
<th>Priority</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="obj in array | filter: criteria track by $index">
<td ng-bind="obj.$value"></td>
<td ng-bind="obj.$id"></td>
<td ng-bind="obj.$priority"></td>
</tr>
</tbody>
</table>
</body>
</html>
Angular javascript array is empty?
I have an array of checkboxes databound to an angular scoped list
I need to check a few checkboxes and send bind them to a second angular scoped array:
My HTML:
<tr ng-repeat="item in pagedItems[currentPage]"
ng-controller="DealerComMaintainCtrl">
<td align="center">
<input type="checkbox" id="{{item.IdArticle}}"
ng-value="item.IdArticle"
ng-checked="selected.indexOf(item.IdArticle) > -1"
ng-click="toggleSelect(item.IdArticle)" />
</td>
<td>
<a href="/Dealercoms/ArticleDownload?FileName={{item.FileName}}&IdArticle={{item.IdArticle}}"
class="btn btn-xs btn-total-red btn-label"><i class="ti ti-download"></i></a>
</td>
<td>{{item.DateArticle | date:'dd/MM/yyyy'}}</td>
<td>{{item.Title}}</td>
<td>{{item.Archive}}</td>
</tr>
And JS in the controller:
$scope.selected = [];
$scope.toggleSelect = function toggleSelect(code) {
var index = $scope.selected.indexOf(code)
if (index == -1) {
$scope.selected.push(code)
} else {
$scope.selected.splice(index, 1)
}
}
$scope.ArchiveDocs = function() {
var selectedoptionz = $scope.selection;
console.log(selectedoptionz);
};
I tried your code and i fixed the problem, by adding the controller on an element above the ng-repeat. The alert is only to check, what is in the selected-array. This is the code, which works fine on my system:
<html>
<head>
</head>
<body ng-app="app">
<table ng-controller="DealerComMaintainCtrl">
<tbody>
<tr ng-repeat="item in pagedItems" >
<td align="center">
<input type="checkbox" id="{{item.IdArticle}}" ng-value="item.IdArticle" ng-checked="selected.indexOf(item.IdArticle) > -1" ng-click="toggleSelect(item.IdArticle)" />
</td>
<td><i class="ti ti-download"></i></td>
<td>{{item.DateArticle | date:'dd/MM/yyyy'}}</td>
<td>{{item.Title}}</td>
<td>{{item.Archive}}</td>
</tr>
</tbody>
</table>
<!-- jQuery -->
<script src="./jquery-2.1.4/jquery.min.js"></script>
<!-- AngularJS -->
<script src="./angular-1.4.5/angular.min.js"></script>
<script>
var app = angular.module("app", []);
app.controller("DealerComMaintainCtrl", function($scope){
$scope.pagedItems = [
{IdArticle: 1, Title: "test1", Archive: "archiv1"},
{IdArticle: 2, Title: "test2", Archive: "archiv1"},
{IdArticle: 3, Title: "test3", Archive: "archiv1"},
{IdArticle: 4, Title: "test4", Archive: "archiv1"}
];
$scope.selected = [];
$scope.toggleSelect = function toggleSelect(code) {
var index = $scope.selected.indexOf(code)
if (index == -1) {
$scope.selected.push(code)
}
else {
$scope.selected.splice(index, 1)
}
alert(JSON.stringify($scope.selected));
}
});
</script>
</body>
</html>
Just try it, i hope it solve your problem...
Someone help me please!
Lets say I have an a list of a checkboxes, each checkbox have an ID.
I would like to $scope an array with checked checkboxes IDs.
<div ng-app="myapp">
<div ng-controller="ctrlParent">
<table>
<tr ng-repeat="(key, value) in providers">
<td><input type="checkbox" ng-model="ids[value.Id]"> {{value}} </td>
</tr>
</table>
{{ids}}
</div>
And my controller:
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.providers = [{Id:5},{Id:6},{Id:8},{Id:10}];
$scope.ids = {};
});
Now my array output (if all check boxes are checked) is: {"5":true,"6":true,"8":true,"10":true}
And I would like: [{Id:5},{Id:6},{Id:8},{Id:10}]
this is a possible solution:
<input type="checkbox" ng-model="ids[$index]" ng-true-value="
{{value}}" ng-false-value="{{undefined}}"/>{{value}}
In this way, you will have an array of objects, because you are assigning ids[$index] = value.
There is a cons however: when you double check a checkbox, you will have an empty element in the array.
var app = angular.module('myapp', []);
app.controller('ctrlParent', function($scope) {
$scope.providers = [{
Id: 5
}, {
Id: 6
}, {
Id: 8
}, {
Id: 10
}];
$scope.ids = [];
$scope.$watchCollection('ids', function(newVal) {
for (var i = 0; i < newVal.length; ++i) {
console.log(newVal[i]);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<div ng-controller="ctrlParent">
<table>
<tr ng-repeat="(key,value) in providers">
<td>
<input type="checkbox" ng-model="ids[$index]" ng-true-value="{{value}}" ng-false-value="{{undefined}}" />{{value}}
</td>
</tr>
</table>{{ids}}</div>
</div>
http://jsfiddle.net/b9jj0re2/3/
<input type="checkbox" ng-model="ids[$index]" ng-true-value="{{value}}" >
Addign the ng-true-value directive will solve the problem
and in controller change the ids from object to array
plunker