AngularFire searching key node and assign to variable - angularjs

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>

Related

How can i make dynamic ng-repeat using angularjs?

Below I have added my data
[{
"name":"testapp",
"version":"2.0",
"description":"testapp",
"applicationenvironment":"angularjs"
}]
I want to make ng-repeat but I don't want to hard code any field (name, version, description, applicationenvironment)
How can I achieve this?
MY expectation :
IN TABLE it should come like this
Your array should be an object. So your structure simplifies quite a lot. Just extract key and values from your object and loop over it for each row. Then display key and values in separate columns per row:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.table = [{
"name": "testapp",
"version": "2.0",
"description": "testapp",
"applicationenvironment": "angularjs"
}]
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr ng-repeat="(key, value) in table[0]">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>
</body>
</html>
Although I don't recommend you to have this strucuture, you can do something like this:
angular.module('app', [])
.controller('appController', function () {
this.data = {
"name":"testapp",
"version":"2.0",
"description":"testapp",
"applicationenvironment":"angularjs"
};
});
And your HTML would be something like this:
<div ng-app="app" ng-controller="appController as vm">
<ul>
<li ng-repeat="(key, value) in vm.data"> {{ key }} : {{ value }}</li>
</ul>
</div>
If you still need to have the data inside an array as you've wrote in the question, you would have to iterate over both the array and the object.
Now since your data source is an array, you need to do two nested ng-repeats
let app = angular.module("table",[]);
app.controller("tableCtrl", ["$scope", function($scope){
$scope.data = [{
"name":"testapp",
"version":"2.0",
"description":"testapp",
"applicationenvironment":"angularjs"
},
{
"name":"testapp 2",
"version":"2.1",
"description":"testapp 2",
"applicationenvironment":"angularjs"
}];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="table" ng-controller="tableCtrl">
<table ng-repeat="row in data">
<tr><td>Key</td><td>Value</td></tr>
<tr ng-repeat="(key,value) in row">
<td>{{key}}</td><td>{{value}}</td>
</tr>
</table>
</div>
Now if you do this, your data structure should yield the wanted result
You need to loop twice: Once through each the entire array of objects to access each object, and then inside each object to access individual key-value pairs.
I have posted the code below:
angular.module('app', [])
.controller('Controller1', function () {
this.data = {
"name":"testapp",
"version":"2.0",
"description":"testapp",
"applicationenvironment":"angularjs"
};
});
<div ng-app="app" ng-controller="Controller1 as c1">
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr ng-repeat="c in c1.data">
<table>
<tr ng-repeat="(key, value) in c">
<td> {{ key }} </td>
<td> {{ value }} </td>
</tr>
</table>
</tr>
</table>
</div>

Angular Js swap columns in table

I would like to swap 2 columns in a table. Finally, I succeeded the change, but only the data. The attributes of the cell (style, id, class) didn't move. I tried to move attributes with jquery (i know, not an elegant method), but it was only symptomatic treatment. After clicking the data reload button, the attributes restored.
How can I change the columns order with all attributes?
my code: https://codepen.io/qwertz_/pen/YxWMBO
<!DOCTYPE html>
<html>
<head>
<title>angT</title>
<script type="text/javascript" src="http://code.angularjs.org/angular-1.0.0rc10.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<style>
th, td{padding: 3px 20px;border: 1px solid red;}
</style>
</head>
<body>
<div ng-controller="MyCtrl" ng-app="myApp">
<button ng-click="swap(0)">first2second</button>
<button ng-click="reload()">reload</button>
<table id="myTable" >
<tr ng-repeat="row in ths">
<th class="oo1">{{col(row, 0)}}</th>
<th class="oo2">{{col(row, 1)}}</th>
<th class="oo3">{{col(row, 2)}}</th>
<th class="oo4">{{col(row, 3)}}</th>
</tr>
<tr ng-repeat="row in rows">
<td class="o1" style="background-color:yellow;">{{col(row, 0)}}</td>
<td class="o2" style="background-color:pink;">{{col(row, 1)}}</td>
<td class="o3" style="background-color:green;">{{col(row, 2)}}</td>
<td class="o4" style="background-color:blue;">{{col(row, 3)}}</td>
</tr>
</table>
</div>
<script type='text/javascript'>
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.mycol = new Array();
$scope.mycol[0] = 'id';
$scope.mycol[1] = 'name';
$scope.mycol[2] = 'db';
$scope.mycol[3] = 'let';
$scope.reload = function()
{
$scope.rows=[{id:parseInt(Math.random()*10000),name:"Liv","db":21,let:"r"},{id:parseInt(Math.random()*10000),name:"Mike",db:30,let:"u"}];
};
$scope.swap = function(i) {
var temp = $scope.mycol[i];
$scope.mycol[i] = $scope.mycol[(i+1)];
$scope.mycol[(i+1)] = temp;
};
$scope.col = function(row, mycol) {
return row[$scope.mycol[mycol]];
};
$scope.reload();
$scope.ths=[{id:"id",name:"name","db":"db",let:"letter"}];
}
</script>
</body>
Thx a lot
Simple way
You can bind colors to header name as:
$scope.styles = {
id: "yellow",
name: "pink"
};
and table will look like:
<tr ng-repeat="row in rows">
<td class="o1" ng-style="{'background-color':styles[mycol[0]]}">{{col(row, 0)}}</td>
<td class="o2" ng-style="{'background-color':styles[mycol[1]]}">{{col(row, 1)}}</td>
<td class="o3" style="background-color:green;">{{col(row, 2)}}</td>
<td class="o4" style="background-color:blue;">{{col(row, 3)}}</td>
</tr>
Once header value changes, colors will change too
Codepen DEMO
More complicated but generic
You can achieve it by replacing all table with directive (headers + data) and by using $compile rebuild all HTML table.

adding a cell to table using add button

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.

Angular javascript array is empty?

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...

angular filter on an object property in ngRepeat doesn't seem to work with 'track by'

I have an map of data items I'm displaying in a table that gets refreshed with new values in the controller (hence the track by key). This all works fine.
If I try to throw an angular filter into the mix, it ignores the filter and displays all the data.
(BTW, items in data are being filled in by a callback from data coming from websocket - maybe this is causing the problem)
What am I missing here?
<label>Filter by Id <input ng-model="search.id"></label><br>
<table class="table table-striped">
<tr>
<th>Id</th>
<th>type</th>
<th>value</th>
<th>time</th>
</tr>
<tr ng-repeat="item in data | filter:search track by item.key">
<td>{{item.id}}</td>
<td>{{item.type}}</td>
<td>{{item.value}}</td>
<td>{{item.timestamp}}</td>
</tr>
</table>
controller:
DataService.addListener(listener);
$scope.data = {};
//incoming data from a websocket
function listener(data) {
var key = data.stuff.id1 + ':' + data.stuff.id2;
var lineItem = {
'id' : data.stuff.id1,
'type' : data.stuff.id2,
'value' : data.data.value,
'timestamp' : new Date(data.stuff.ts).toTimeString(),
'key' :key
};
$scope.$apply(function() {
$scope.data[key] = lineItem;
});
}
note that item.key is a property that uniquely identifies the item in the map of data.
You are filtering by search and not search.id since your input's model is set as search.id. Try this:
<tr ng-repeat="item in data | filter:search.id track by item.key">
Problem was filter doesn't work on maps. Derp.
Stole a map filter from this answer here, now it all works.
plunker
http://plnkr.co/edit/u5D3tGGKDOY4P4u6T1GZ?p=preview
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.1" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="TestCtrl">
<label>Filter by Id <input ng-model="search.id"></label><br>
<table border="1">
<tr>
<th>Id</th>
<th>value</th>
</tr>
<tr ng-repeat="item in data | mapFilter:search track by item.key">
<td>{{item.id}}</td>
<td>{{item.value}}</td>
</tr>
</table>
</body>
</html>
script:
angular.module('app', []).controller('TestCtrl', function($scope) {
$scope.data = {};
for (var i = 0; i < 20; i++) {
var item = {
id: randomWord() + " " + randomWord(),
key: 'key ' + i,
value: Math.floor(Math.random() * 300),
};
$scope.data[item.key] = item;
}
})
.filter('mapFilter', function($filter) {
var filter = $filter('filter');
return function(map, expression, comparator) {
if (! expression) return map;
var result = {};
angular.forEach(map, function(data, index) {
if (filter([data], expression, comparator).length)
result[index] = data;
});
return result;
}
});
var words = [
'lunville',
'pandybat',
'demurrer',
'slighter',
'reguline',
'exploder',
'krakatoa',
'wirespun',
];
function randomWord() {
return words[ Math.floor(Math.random() * 8)];
}

Resources