Concat 2 datas from json Angular ng-repeat - javascript

I try to put data from another array into one part in table.
My first json "names" :
[
{
"name": "AAAAAA",
"down": "False"
},
{
"name": "BBBBBB",
"down": "True"
},
{
"name": "CCCCC",
"down": "False"
}
]
Second json "data" :
[
{
"data": "35%"
}
]
Javascript:
var app = angular.module('app', []);
app.service('service', function($http, $q){
this.getNames = function () {
var names = $http.get('names.json', {cache: false});
var datas = $http.get('data.json', {cache: false});
return $q.all({datas,names});
};
});
app.controller('FirstCtrl', function($scope, service, $http) {
var promise = service.getNames();
promise.then(function (data) {
$scope.names = data.names.data;
$scope.datas = data.datas.data;
$scope.namesanddata = $scope.names.concat($scope.datas);
console.log($scope.namesplit);
console.log($scope.datas);
});
});
Table in HTML :
div ng-controller="FirstCtrl"
<table>
<tbody>
<tr ng-repeat="name in namesanddata">
<td>{{name.name}}</td>
<td ng-if="name.down=== 'False'">{{name.down}}</td>
<td ng-if="name.down !== 'False'">{{name.data}}</td>
</tr>
</tbody>
</table>
</div>
My problem - <td ng-if="name.down !== 'False'">{{name.data}}</td>dont show in table. in console.log it concat to array like 4 object and probably by this it don't show in table next to {{name.name}}, but i don't know how to show {{name.data}} from another json in table instead {{name.down}}.
Thanks for answers in advance.

To give you an output of:
AAAAAA False
BBBBBB 35%
CCCCC False
Remove this line from the Controller:
$scope.namesanddata = $scope.names.concat($scope.datas);
Then either:
Solution 1 - Inline in the view
Change your ng-repeat as follows:
<tr ng-repeat="name in names">
<td>{{ name.name }}</td>
<td>{{ (name.down === 'False') ? name.down : datas[0].data }}</td>
</tr>
OR
Solution 2 - Keep the view clean by using a Filter
app.filter('myFilter', function () {
return function(items, datas) {
var filtered = [];
angular.forEach(items, function (i) {
if (i.down !== "False")
i.down = datas[0].data;
filtered.push(i);
});
return filtered;
}
});
Change your ng-repeat as follows:
<tr ng-repeat="name in names | myFilter: datas">
<td>{{ name.name }}</td>
<td>{{ name.down }}</td>
</tr>

Related

Service for Angular module md-data-table

In the readme of Angular module "md-data-table" it says "Assume we have a $nutrition service". I tried adding a service (makerService), with a return of data. But I can't see the data represented on the screen. I tried different JSON formats, as an error I get:
$makerService.makers.get is not a function
This is my Javascript code:
(function() {
'use strict';
angular.module('BowbleCRM', [
'ngMaterial',
'md.data.table'
])
.service('$makerService', function () {
var makers = {
"makers" : [
{"full_name": "Jan", "email": "jan#test.nl"},
{"full_name": "Pieter", "email": "pieter#test.nl"}
]
};
return makers;
})
.controller('BowbleCRMController', ['$makerService', '$scope', BowbleCRMController]);
function BowbleCRMController($makerService, $scope) {
'use strict';
$scope.currentNav = 'importeren';
$scope.selected = [];
$scope.query = {
order: 'full_name',
limit: 5,
page: 1
};
function success(makers) {
console.log(makers);
$scope.makers = makers;
}
$scope.getMakers = function () {
$scope.promise = $makerService.makers.get($scope.query, success).$promise;
};
}
})();
And this is a part of my HTML.
<md-toolbar class="md-table-toolbar md-default">
<div class="md-toolbar-tools">
<span>Alle makers</span>
</div>
</md-toolbar>
<!-- exact table from live demo -->
<md-table-container>
<table md-table md-row-select multiple ng-model="selected" md-progress="promise">
<thead md-head md-order="query.order" md-on-reorder="getMakers">
<tr md-row>
<th md-column><span>Volledige naam</span></th>
<th md-column><span>E-Mail adres</span></th>
</tr>
</thead>
<tbody md-body>
<tr md-row md-select="maker" md-select-id="full_name" md-auto-select ng-repeat="maker in makers.data">
<td md-cell>{{maker.full_name}}</td>
<td md-cell>{{maker.email}}</td>
</tr>
</tbody>
</table>
</md-table-container>
<md-table-pagination md-limit="query.limit" md-limit-options="[5, 10, 15]" md-page="query.page" md-total="{{makers.length}}" md-on-paginate="getMakers" md-page-select></md-table-pagination>
How can I make a correct service, and showing the data with the Angular module "md-data-table"?
You don't have a function get on $makerService, you just return makers which is an object.
If you want to call a get promise you must implement it on makerService. Something like
.service('$makerService', function () {
var makers = {
"makers" : [
{"full_name": "Jan", "email": "jan#test.nl"},
{"full_name": "Pieter", "email": "pieter#test.nl"}
]
};
function get(params){
//..implement your logic here (for your controller code, this should return a promise)
}
return {
makers: makers,
get: get
};
})
And in your controller you can call it like this:
$scope.getMakers = function () {
$scope.promise = $makerService.get($scope.query, success).$promise;
};

how to import multiple JSON data into table using ng-Tables

I am using ng-table for AngularJS and i am using single JSON file for the table data. i want to import multiple JSON files into a single table. I am able to import single JSON file using this code below.
Thank you in advance.
HTML
<table ng-table="tableParams" show-filter="true" class="table ng-table-responsive">
<tr ng-repeat="user in $data">
<td data-title="'ID'" sortable="'ID'">
{{user.ID}}
</td>
<td data-title="'Name'" sortable="'Name'" filter="{ 'name': 'Name' }">
{{user.Name}}
</td>
<td data-title="'Email'" sortable="'email'">
{{user.email}}
</td>
<td data-title="'Address'" sortable="'address'">
{{user.address}}
</td>
<td data-title="'PersonalEmail'" sortable="'personalemail'">
{{user.personalemail}}
</td>
<td data-title="'PhoneNo'" sortable="'phoneno'">
{{user.phoneno}}
</td>
<td data-title="'Status'" sortable="'status'">
{{user.status}}
</td>
</tr>
</table>
JavaScript
var app = angular.module('main', ['ngTable']).controller('DemoCtrl', function($scope, ngTableParams, NameService) {
var data = NameService.data;
$scope.tableParams = new ngTableParams(
{
page: 1, // show first page
count: 10, // count per page
sorting: {name:'asc'}
},
{
total: 0, // length of data
getData: function($defer, params) {
NameService.getData($defer,params,$scope.filter);
}
});
$scope.$watch("filter.$", function () {
$scope.tableParams.reload();
});
});
app.service("NameService", function($http, $filter){
function filterData(data, filter){
return $filter('filter')(data, filter)
}
function orderData(data, params){
return params.sorting() ? $filter('orderBy')(data, params.orderBy()) : filteredData;
}
function sliceData(data, params){
return data.slice((params.page() - 1) * params.count(), params.page() * params.count())
}
function transformData(data,filter,params){
return sliceData( orderData( filterData(data,filter), params ), params);
}
var service = {
cachedData:[],
getData:function($defer, params, filter){
if(service.cachedData.length>0){
console.log("using cached data")
var filteredData = filterData(service.cachedData,filter);
var transformedData = sliceData(orderData(filteredData,params),params);
params.total(filteredData.length)
$defer.resolve(transformedData);
}
else{
console.log("fetching data")
$http.get("json/1.json").success(function(resp)
{
angular.copy(resp,service.cachedData)
params.total(resp.length)
var filteredData = $filter('filter')(resp, filter);
var transformedData = transformData(resp,filter,params)
$defer.resolve(transformedData);
});
}
}
};
return service;
});
Retrieve all your JSON content with $q.all() and merge your arrays in the callback. Finally pass the resulting array to ng-table.

How to get result data in Angular promise request?

I am studying Angular and I have a problem with my code. I am trying to create an ajax request by using promise and service. My output in ajax access in successful but I can't display it in the view.
Here's some of my code:
<div ng-app="promiseCall">
<div ng-controller="promiseCtrl">
<button tyle="button" class="btn btn-default" ng-click="promiseCallRequest()">Promise Call</button>
<table class="table table-bordered table-hovered">
<thead>
<tr>
<td class="text-center"><label>ID</label></td>
<td class="text-center"><label>TITLE</label></td>
<td class="text-center"><label>BODY</label></td>
<td class="text-center"><label>CREATED AT</label></td>
<td class="text-center"><label>UPDATED AT</label></td>
</tr>
</thead>
<tbody>
<!-- no output -->
<tr ng-repeat="item in noteListing">
<td>{{ item.id }}</td>
<td>{{ item.title }}</td>
<td>{{ item.body }}</td>
<td>{{ item.created_at }}</td>
<td>{{ item.updated_at }}</td>
</tr>
</tbody>
</table>
</div>
</div>
angular.module('promiseCall',[])
.controller('promiseCtrl', function($scope, $log, noteData) {
$scope.promiseCallRequest = function() {
var getPromiseCallData = noteData.getNoteData();
getPromiseCallData.then({
function(payload) {
console.log(payload); //no output :(
//$scope.noteListing = payload.data;
},
function(errorPayload) {
$log.error('Failure request in note', errorPayload);
}
});
}
}).factory('noteData', function($http, $log, $q) {
return {
getNoteData: function() {
var deferred = $q.defer();
$http.get("<?php echo site_url('tutorial/getAjaxData'); ?>")
.success(function(data){
/*
deferred.resolve({
id: data.id,
title: data.title
});
*/
//console.log('success'); -- ok
})
.error(function(msg, code){
deferred.reject(msg);
$log.error(msg, code);
alert('there must be an error!');
});
return deferred.promise;
}
}
});
Here's the JSON output:
{"article_data":[{"id":"1","title":"sample updated 1","body":"sample 1","created_at":"2015-06-15 15:37
:28","updated_at":"2015-06-15 21:38:46"},{"id":"2","title":"sample 2","body":"sample 2","created_at"
:"2015-06-15 15:37:54","updated_at":"2015-06-15 15:37:54"}]}
Try to remove the {} in your getPromiseCallData.then({});.
E.g.
$scope.promiseCallRequest = function() {
var getPromiseCallData = noteData.getNoteData();
getPromiseCallData.then(
function(payload) {
console.log(payload); //no output :(
//$scope.noteListing = payload.data;
},
function(errorPayload) {
$log.error('Failure request in note', errorPayload);
}
);
};
Hope it helps.
try the below code:
....
getPromiseCallData.then(function(payload) {
console.log(payload); //no output :(
//$scope.noteListing = payload.data;
}).catch(function(errorPayload) {
$log.error('Failure request in note', errorPayload);
});
...
getNoteData: function() {
return $http.get("<?php echo site_url('tutorial/getAjaxData'); ?>");
}
in getNoteData, what you did was a promise anti-pattern, you already have a promise, no need to create another wrapper for it.
Edit:
if you want to log the service's success and error, you could simply do, you still don't need an additional promise:
getNoteData: function() {
return $http.get("<?php echo site_url('tutorial/getAjaxData'); ?>").then(function(data){
//some log
return data;
}, function(err){
// log err
return err;
});
}

AngularJS select with ng-options not updating referenced object property in the parent scope

My select is populating with the contents of the model, but when I select an option, the model does not update.
I'm using ng-options, not ng-repeat and my ng-model is an object on the parent scope, not a primitive, so I think I've avoided the "child-scope" issues I've seen on similar posts. I've recreated the problem on jsfiddle:
http://jsfiddle.net/bobweil/wfdjrej5/
When the user clicks on a row in the table, a small form shows up below that row, permitting a new status value to be selected for that row for posting to the backend service.
Here's my javascript:
angular.module('myApp', [])
.controller('TaskCtrl', function HomeController($scope, $filter) {
$scope.statusMasters = [{
"Id": 1,
"DisplayOrder": 100,
"Text": "Review"
}, {
"Id": 2,
"DisplayOrder": 200,
"Text": "New"
}, {
"Id": 3,
"DisplayOrder": 300,
"Text": "Working"
}, {
"Id": 4,
"DisplayOrder": 400,
"Text": "Complete"
}]
$scope.tasks = [{
"taskId": 1000,
"Descr": "My first task",
"statusId": 1
}, {
"taskId": 2000,
"Descr": "My second task",
"statusId": 1
}, {
"taskId": 3000,
"Descr": "My third task",
"statusId": 1
}];
$scope.selectedTask = null;
$scope.newTaskStatus = {};
$scope.opGroup = "A";
$scope.selectTask = function (thisTask) {
$scope.selectedTask = thisTask;
$scope.newTaskStatus = {};
$scope.newTaskStatus.taskId = thisTask.taskId;
$scope.newTaskStatus.statusId = thisTask.statusId;
};
$scope.isSelected = function (thisTask) {
if (thisTask.hasOwnProperty('taskId')) {
return $scope.selectedTask.taskId === thisTask.taskId;
} else return false;
};
});
And here's my html:
<div ng-controller="TaskCtrl">
<table class="table table-bordered">
<thead>
<tr>
<th>Task #</th>
<th>Description</th>
<th>StatusId</th>
<th>Status Text</th>
</tr>
</thead>
<tbody ng-repeat="item in tasks" ng-click="selectTask(item)" ng-switch on="isSelected(item)">
<tr>
<td>{{item.taskId }}</td>
<td>{{item.Descr}}</td>
<td>{{item.statusId}}</td>
<td>{{statusMasters[item.statusId - 1].Text}}</td>
</tr>
<tr ng-switch-when="true">
<td colspan="10">
<div>Debug: contents of new task status object: <pre>{{newTaskStatus | json}}</pre>
</div>
<label>Select a new status for task {{newTaskStatus.taskId}}:</label>
<select ng-model="newTaskStatus.taskId" ng-show="(opGroup == 'A')" class="form-control" ng-options="rec.Id as rec.Text for rec in statusMasters | orderBy : 'DisplayOrder'"></select>
<select ng-model="newTaskStatus.taskId" ng-show="(opGroup == 'B')" class="form-control" ng-options="rec.Id as rec.Text for rec in statusMasters | orderBy : 'DisplayOrder'"></select>
</td>
</tr>
</tbody>
</table>
Part of the issue is you are trying to set a click event on the tbody, you need to set the ng-click on the row (tr).
Secondly, unless it is needed for another reason, I wouldn't duplicate the values from the "selectedTask" into a "newTaskStatus" when you are planning on changing the status and sending back that value, it can all be done with one object on the scope.
Third, you could clean up your .js a little by changing the 'ng-switch on' to do the check if it is selected. It replaces an entire function with a comparison.
I would do something like this.
<tbody ng-repeat="item in tasks" ng-switch on="selectedTask.taskId == item.taskId">
<tr ng-click="selectTask(item)">
<td>{{item.taskId }}</td>
<td>{{item.Descr}}</td>
<td>{{item.statusId}}</td>
<td>{{statusMasters[item.statusId - 1].Text}}</td>
</tr>
<tr ng-switch-when="true">
<td colspan="10">
<div>Debug: contents of new task status object: <pre>{{selectedTask | json}}</pre>
</div>
<label>Select a new status for task {{selectedTask.taskId}}:</label>
<select ng-model="selectedTask.statusId" ng-show="(opGroup == 'A')" class="form-control" ng-options="rec.Id as rec.Text for rec in statusMasters | orderBy : 'DisplayOrder'"></select>
<select ng-model="selectedTask.statusId" ng-show="(opGroup == 'B')" class="form-control" ng-options="rec.Id as rec.Text for rec in statusMasters | orderBy : 'DisplayOrder'"></select>
</td>
</tr>
</tbody>
With the .js I would remove the unnecessary items:
$scope.selectedTask = null;
$scope.opGroup = "A";
$scope.selectTask = function (thisTask) {
$scope.selectedTask = thisTask;
};
$scope.isSelected = function (thisTask) {
if (thisTask.hasOwnProperty('taskId')) {
return $scope.selectedTask.taskId === thisTask.taskId;
} else return false;
};
I forked your jsfiddle here to demonstrate what I mean. Good Luck!

apply formatting filter dynamically in a ng-repeat

My goal is to apply a formatting filter that is set as a property of the looped object.
Taking this array of objects:
[
{
"value": "test value with null formatter",
"formatter": null,
},
{
"value": "uppercase text",
"formatter": "uppercase",
},
{
"value": "2014-01-01",
"formatter": "date",
}
]
The template code i'm trying to write is this:
<div ng-repeat="row in list">
{{ row.value | row.formatter }}
</div>
And i'm expecting to see this result:
test value with null formatter
UPPERCASE TEXT
Jan 1, 2014
But maybe obviusly this code throws an error:
Unknown provider: row.formatterFilterProvider <- row.formatterFilter
I can't immagine how to parse the "formatter" parameter inside the {{ }}; can anyone help me?
See the plunkr http://plnkr.co/edit/YnCR123dRQRqm3owQLcs?p=preview
The | is an angular construct that finds a defined filter with that name and applies it to the value on the left. What I think you need to do is create a filter that takes a filter name as an argument, then calls the appropriate filter (fiddle) (adapted from M59's code):
HTML:
<div ng-repeat="row in list">
{{ row.value | picker:row.formatter }}
</div>
Javascript:
app.filter('picker', function($filter) {
return function(value, filterName) {
return $filter(filterName)(value);
};
});
Thanks to #karlgold's comment, here's a version that supports arguments. The first example uses the add filter directly to add numbers to an existing number and the second uses the useFilter filter to select the add filter by string and pass arguments to it (fiddle):
HTML:
<p>2 + 3 + 5 = {{ 2 | add:3:5 }}</p>
<p>7 + 9 + 11 = {{ 7 | useFilter:'add':9:11 }}</p>
Javascript:
app.filter('useFilter', function($filter) {
return function() {
var filterName = [].splice.call(arguments, 1, 1)[0];
return $filter(filterName).apply(null, arguments);
};
});
I like the concept behind these answers, but don't think they provide the most flexible possible solution.
What I really wanted to do and I'm sure some readers will feel the same, is to be able to dynamically pass a filter expression, which would then evaluate and return the appropriate result.
So a single custom filter would be able to process all of the following:
{{ammount | picker:'currency:"$":0'}}
{{date | picker:'date:"yyyy-MM-dd HH:mm:ss Z"'}}
{{name | picker:'salutation:"Hello"'}} //Apply another custom filter
I came up with the following piece of code, which utilizes the $interpolate service into my custom filter. See the jsfiddle:
Javascript
myApp.filter('picker', function($interpolate ){
return function(item,name){
var result = $interpolate('{{value | ' + arguments[1] + '}}');
return result({value:arguments[0]});
};
});
One way to make it work is to use a function for the binding and do the filtering within that function. This may not be the best approach: Live demo (click).
<div ng-repeat="row in list">
{{ foo(row.value, row.filter) }}
</div>
JavaScript:
$scope.list = [
{"value": "uppercase text", "filter": "uppercase"}
];
$scope.foo = function(value, filter) {
return $filter(filter)(value);
};
I had a slightly different need and so modified the above answer a bit (the $interpolate solution hits the same goal but is still limited):
angular.module("myApp").filter("meta", function($filter)
{
return function()
{
var filterName = [].splice.call(arguments, 1, 1)[0] || "filter";
var filter = filterName.split(":");
if (filter.length > 1)
{
filterName = filter[0];
for (var i = 1, k = filter.length; i < k; i++)
{
[].push.call(arguments, filter[i]);
}
}
return $filter(filterName).apply(null, arguments);
};
});
Usage:
<td ng-repeat="column in columns">{{ column.fakeData | meta:column.filter }}</td>
Data:
{
label:"Column head",
description:"The label used for a column",
filter:"percentage:2:true",
fakeData:-4.769796600014472
}
(percentage is a custom filter that builds off number)
Credit in this post to Jason Goemaat.
Here is how I used it.
$scope.table.columns = [{ name: "June 1 2015", filter: "date" },
{ name: "Name", filter: null },
] etc...
<td class="table-row" ng-repeat="column in table.columns">
{{ column.name | applyFilter:column.filter }}
</td>
app.filter('applyFilter', [ '$filter', function( $filter ) {
return function ( value, filterName ) {
if( !filterName ){ return value; } // In case no filter, as in NULL.
return $filter( filterName )( value );
};
}]);
I improved #Jason Goemaat's answer a bit by adding a check if the filter exists, and if not return the first argument by default:
.filter('useFilter', function ($filter, $injector) {
return function () {
var filterName = [].splice.call(arguments, 1, 1)[0];
return $injector.has(filterName + 'Filter') ? $filter(filterName).apply(null, arguments) : arguments[0];
};
});
The newer version of ng-table allows for dynamic table creation (ng-dynamic-table) based on a column configuration. Formatting a date field is as easy as adding the format to your field value in your columns array.
Given
{
"name": "Test code",
"dateInfo": {
"createDate": 1453480399313
"updateDate": 1453480399313
}
}
columns = [
{field: 'object.name', title: 'Name', sortable: 'name', filter: {name: 'text'}, show: true},
{field: "object.dateInfo.createDate | date :'MMM dd yyyy - HH:mm:ss a'", title: 'Create Date', sortable: 'object.dateInfo.createDate', show: true}
]
<table ng-table-dynamic="controller.ngTableObject with controller.columns" show-filter="true" class="table table-condensed table-bordered table-striped">
<tr ng-repeat="row in $data">
<td ng-repeat="column in $columns">{{ $eval(column.field, { object: row }) }}</td>
</tr>
</table>
I ended up doing something a bit more crude, but less involving:
HTML:
Use the ternary operator to check if there is a filter defined for the row:
ng-bind="::data {{row.filter ? '|' + row.filter : ''}}"
JS:
In the data array in Javascript add the filter:
, {
data: 10,
rowName: "Price",
months: [],
tooltip: "Price in DKK",
filter: "currency:undefined:0"
}, {
This is what I use (Angular Version 1.3.0-beta.8 accidental-haiku).
This filter allows you to use filters with or without filter options.
applyFilter will check if the filter exists in Angular, if the filter does not exist, then an error message with the filter name will be in the browser console like so...
The following filter does not exist: greenBananas
When using ng-repeat, some of the values will be undefined. applyFilter will handle these issues with a soft fail.
app.filter( 'applyFilter', ['$filter', '$injector', function($filter, $injector){
var filterError = "The following filter does not exist: ";
return function(value, filterName, options){
if(noFilterProvided(filterName)){ return value; }
if(filterDoesNotExistInAngular(filterName)){ console.error(filterError + "\"" + filterName + "\""); return value; }
return $filter(filterName)(value, applyOptions(options));
};
function noFilterProvided(filterName){
return !filterName || typeof filterName !== "string" || !filterName.trim();
}
function filterDoesNotExistInAngular(filterName){
return !$injector.has(filterName + "Filter");
}
function applyOptions(options){
if(!options){ return undefined; }
return options;
}
}]);
Then you use what ever filter you want, which may or may not have options.
// Where, item => { name: "Jello", filter: {name: "capitalize", options: null }};
<div ng-repeat="item in items">
{{ item.name | applyFilter:item.filter.name:item.filter.options }}
</div>
Or you could use with separate data structures when building a table.
// Where row => { color: "blue" };
// column => { name: "color", filter: { name: "capitalize", options: "whatever filter accepts"}};
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.name] | applyFilter:column.filter.name:column.filter.options }}
</td>
</tr>
If you find that you require to pass in more specific values you can add more arguments like this...
// In applyFilter, replace this line
return function(value, filterName, options){
// with this line
return function(value, filterName, options, newData){
// and also replace this line
return $filter(filterName)(value, applyOptions(options));
// with this line
return $filter(filterName)(value, applyOptions(options), newData);
Then in your HTML perhaps your filter also requires a key from the row object
// Where row => { color: "blue", addThisToo: "My Favorite Color" };
// column => { name: "color", filter: { name: "capitalize", options: "whatever filter accepts"}};
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns">
{{ row[column.name] | applyFilter:column.filter.name:column.filter.options:row.addThisToo }}
</td>
</tr>

Categories

Resources