how to get data from json file using angularjs - javascript

I am getting data from json file to display in a table, but first time only i got data from getdata() next time i got following error:
Uncaught TypeError: Cannot read property 'length' of undefined Controller.js:95
$http return value is fine, i got all data from json file first time, next time i could not get data from getdata().
getData() function is not working properly, it is working only first time, next time i could not get data.
how to solve this issue.
controller.js
var app = angular.module('main', ['ngTable', 'claimApp']);
app.controller('DemoCtrl', function ($scope, $filter, ngTableParams, appFactory,$http) {
$scope.datasets = ["1", "2", "3"];
$scope.dataset = "1";
var data1 = [];
var data2 = [];
var data3 = [];
$scope.totalCnt = function () {
return window.document.getElementById("tablesort").getElementsByTagName("TR").length - 1;
};
var getData = function () {
if ($scope.dataset == "1") {
$http.get('json/json0.json').success(function(data) {
data1 = data;
});
return data1;
} else if ($scope.dataset == "2") {
$http.get('json/json1.json').success(function(data) {
data2= data;
});
return data2;
} else if ($scope.dataset == "3") {
$http.get('json/json2.json').success(function(data) {
data3= data;
});
return data3;
}
};
$scope.$watch("dataset", function () {
$("#tablesort").fadeOut('slow', function () {
$scope.tableParams.reload();
$scope.tableParams.page(1);
$("#tablesort").fadeIn('slow');
});
});
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
name: 'asc' // initial sorting
}
}, {
total: function () {
return getData().length;
console.info("==="+getData().length);
}, // length of data
getData: function ($defer, params) {
var filteredData = getData();
console.info("filteredData"+filteredData);<!--i could not get this data second time only it is working first time-->
var orderedData = params.sorting() ?
$filter('orderBy')(filteredData, params.orderBy()) :
filteredData;
var lastPage = (1 + Math.floor((orderedData.length - 1) / params.count()));
$("#lastpage").html(lastPage);
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
},
$scope: {
$data: {}
}
});
});

according to the doc
Request transformations:
If the data property of the request configuration object contains an object, serialize it into JSON format.
Response transformations:
If XSRF prefix is detected, strip it (see Security Considerations section below).
If JSON response is detected, deserialize it using a JSON parser.
so use in your response
$http.get('json/json0.json').success(function(data) {
data1 = JSON.parse(data);
});
EDIT
var getData = function () {
if ($scope.dataset == "1") {
$http.get('json/json0.json').success(function(data) {
$scope.response = data;
});
} else if ($scope.dataset == "2") {
$http.get('json/json1.json').success(function(data) {
$scope.response = data;
});
} else if ($scope.dataset == "3") {
$http.get('json/json2.json').success(function(data) {
$scope.response = data;
});
}
return $scope.response;
};

Related

AngularJS filter with a promise

I'm upgrading a filter from a static object to an object retrieved from our database, but I can't seem to get a proper return. This filter takes in an integer which represents a named location, it looks up the location with the key, and returns the name. After troubleshooting, I'm getting close as I can see the object from the database and I can see some of the lookups correctly inside of the then section, but it's not being returned at the end of the filter. Is there a better method on getting this with a filter?
stPartFieldFilters.js
angular.module('app').filter('partLocation', function(stPartMgmtSvc, $q) {
var locs;
function getLocations() {
if(!locs) {
var dfd = $q.defer();
stPartMgmtSvc.getLocations().then(function(res) { locs = res; dfd.resolve(locs); }, function(response) { dfd.reject(response.data.reason) });
return dfd.promise;
}
else {
var dfd = $q.defer();
dfd.resolve(locs);
return dfd.promise;
}
}
function getResults(loc, type) {
var lr = null; // this should be updated once a match is found below
getLocations().then(function(ls) {
if (loc || loc === 0) {
loc = loc.split(',');
if(typeof loc === 'object') {
var res = new Array;
loc.forEach(function(l) {
res.push(ls[l].name)
});
if(!type) { lr = res.toString().replace(',', '<br>'); } // this line provides the correct output; see below (LOCFLTRRES1)
else { lr = res.toString().replace(',', ', '); }
}
else { lr = ls[loc].name; }
}
else { lr = false; };
});
return lr; // return the updated result
}
return function(loc, type) {
return getResults(loc, type); //return the final result for the filter
}
});
inventory.jade
~~~
td.desktop-only {{part.partLoc | partLocation:1}}
~~~
Here is an image of the results of the database object.
Here is an image of the result inside of the filter. This should be set to lr and returned to the main filter function.
Here is the expected result.
Finally, here is the actual result.

Unable to return result from promise

I am trying to read some data from 2 different tables and parse a CSV file before rendering an ejs file.
I can get the data from both tables and from the CSV file but I seem to be unable to return the result.
Pretty sure this is a problem with the way I handle async execution but I fail to see what I am doing wrong.
I've spent the last 2 days reading about this (including the threads around here) and browsing but somehow the answer still escapes me.
First file - usercms.js
app.get('/userscms', function(req, res)
{
existingUsers.getExistingUsers()
.then(function(appUsers)
{
//global users array
//I can display these in my ejs file
globalAppUsers = appUsers;
})
.then(existingUsersAttributesQlik.getExistingUsersAttributesQlik())
.then(function(usersQlikAttributes)
{
//global user attributes array
//undefined data
globalUsersQlikAttributes = usersQlikAttributes;
})
.then(existingSuppliers.parseSuppliersCSV())
.then(function(supplierData)
{
//the result I am expecting
//this prints undefined
console.log(supplierData);
}).then(function()
{
res.render('userscms.ejs',
{
users: globalAppUsers,
attributes: globalUsersQlikAttributes
});
});
});
Second function - getxistingUsers.js (identical to the getExistingUsersAttributesQlik, except for the query)
var userData = [];
var appUsers = [];
(function (exports)
{
exports.getExistingUsers = function ()
{
return promisemysql.createConnection(dbconfig.development).then(function(conn)
{
var result = conn.query("SELECT id, username, firstName, lastName, email, phone, lastLogin, isAdmin, isValid, isPhoneValid, accountCreationDateTime FROM Users");
conn.end();
return result;
}).then(function(rows)
{
return rows;
}).then(function(rows)
{
if (rows.length)
{
userData = [];
appUsers = [];
rows.forEach(function (elem)
{
userData.push(_.toArray(elem));
});
for (i = 0; i < userData.length; i++)
{
var appUser = new appUserModel.AppUser(
userData[i][0],
userData[i][1],
userData[i][2],
userData[i][3],
userData[i][4],
userData[i][5],
userData[i][6],
userData[i][7],
userData[i][8],
userData[i][9],
userData[i][10]);
appUsers.push(_.toArray(appUser));
}
return appUsers;
}
else
{
console.log("NOPE");
return null;
}
}).then(function(appUsers)
{
console.log(appUsers);
return appUsers;
});
};
})(typeof exports === 'undefined' ? this['getExistingUsers'] = {} : exports);
Third file - parseSuppliersCSV.js
var supplierData = [];
var suppliersData = [];
var csvCount = 0;
(function (exports)
{
exports.parseSuppliersCSV = function ()
{
return new Promise(function(resolve, reject)
{
var fileStream = fs.createReadStream("myCSV.csv");
var parser = fastCsv();
csvCount = 0;
supplierData = [];
suppliersData = [];
fileStream
.on("readable", function ()
{
var data;
while ((data = fileStream.read()) !== null)
{
parser.write(data);
}
})
.on("end", function ()
{
parser.end();
});
parser
.on("readable", function ()
{
var data;
while ((data = parser.read()) !== null)
{
if(csvCount >= 1)
{
csvCount++;
var arrayOfStrings = data[0].split(';');
var supplier = new supplierModel.Supplier(arrayOfStrings[0],arrayOfStrings[1]);
suppliersData.push(_.toArray(supplier));
}
else
{
csvCount++;
}
}
})
.on("end", function ()
{
console.log("done");
//all OK here
console.log(suppliersData);
//this doesn't seem to return anything
return suppliersData;
});
});
};
})(typeof exports === 'undefined' ? this['parseSuppliersCSV'] = {} : exports);
Any ideas what I am doing wrong? Am I approaching this the wrong way?
I'll take a guess here and assume the promise you created should resolve to something...instead of returning a value.
.on("end", function ()
{
console.log("done");
//all OK here
console.log(suppliersData);
//this doesn't seem to return anything
return resolve(suppliersData);
});

Config is undefined for $scope.model property

I am implementing a controller for a content picker in Umbraco 7, where I need to change the start node to match a specific content node. However wen I load up the page with the content picker I receive an error saying:
"Cannot read property 'config' of undefined"
In relation to this piece of code:
$scope.model.config.StartNodeId = 1083;
if ($scope.model.config.StartNodeId) {
options.startNodeId = $scope.model.config.StartNodeId;
}
My entire controller:
angular.module("umbraco").controller("UIOMatic.FieldEditors.Pickers.ContentController",
function ($scope, $routeParams, $http, dialogService, entityResource, iconHelper) {
function init() {
if (!$scope.setting) {
$scope.setting = {};
}
var val = parseInt($scope.property.value);
if (!isNaN(val) && angular.isNumber(val) && val > 0) {
$scope.showQuery = false;
entityResource.getById(val, "Document").then(function (item) {
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.node = item;
});
}
$scope.openContentPicker = function () {
var d = dialogService.treePicker({
section: "content",
treeAlias: "content",
multiPicker: false,
callback: populate
});
};
$scope.model.config.StartNodeId = 1083;
if ($scope.model.config.StartNodeId) {
options.startNodeId = $scope.model.config.StartNodeId;
}
$scope.clear = function () {
$scope.id = undefined;
$scope.node = undefined;
$scope.property.value = undefined;
};
function populate(item) {
$scope.clear();
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.node = item;
$scope.id = item.id;
$scope.property.value = item.id;
}
};
if ($scope.valuesLoaded) {
init();
} else {
var unsubscribe = $scope.$on('valuesLoaded', function () {
init();
unsubscribe();
});
}
});
I tried changing the start node ID to 1083, which is what I want, and I can open the content picker just fine, but it won't allow me to save my changes. It also allows for multi-picking, which I have set to false in my config object.
This is the documentation of the content picker from the author:
http://uiomatic.readthedocs.io/en/stable/02.DefaultEditorViews/#content-picker
I think You should initialize $scope.model before assigning value to its object.
use
$scope.model = {}

Angular Nested Promise

I’m really struggling to write a complex function in Angular that depends on promises. This is my first time writing a promise and I'm still not sure I fully understand how to do what I want to do with my code.
I have a variable var query = searchQuery.getQuery() in a controller ProfileNavCtrl. Then in my searchQuery service, getQuery fetches the value of localStorage.getItem('searchQuery') and checks if it’s an empty string or null. If it’s not empty or null, it simply returns the value to the controller. The value should be an array of slugs like ['foo','foo-bar','foo-bar-baz'].
If it is null or empty, it executes an $http.get call to fetch a JSON object and parse it. This is where things break down for me. I need getQuery() to return the value from $http.get (if the initial value of query is null) so that the controller variable query is assigned that value. As it is now, query (in the controller) is always set to null or undefined.
The $http.get call also calls setQuery() so that the query is persisted and future calls are avoided.
Here is my controller:
app.controller('ProfileNavCtrl', ['$scope', '$http', '$location', '$q', 'searchQuery',
function($scope, $http, $location, $q, searchQuery){
var query = searchQuery.getQuery;
// do something with query
And here is my service:
app.service('searchQuery', ['$http', '$timeout', '$q', function($http, $timeout, $q){
var query = [];
this.getQuery = new Promise(function(){
var query = localStorage.getItem('searchQuery');
if(query == "" || query == [""] || query == null){
var slugArray = [];
var query = $http.get('/companies.json')
.then(function(resp) {
if(resp && resp.data) {
for(var i in resp.data) {
var result = resp.data[i];
if(resp.data[i].name){
slugArray.push(resp.data[i].name.toLowerCase().split(' ').join('-'));
}
}
setQuery(slugArray);
} else {
resetQuery();
}
}, function(err) {
resetQuery();
}).then(function(resp){
return resp;
})
return query;
} else {
return query;
};
}).then(function(success){
return success;
});
UPDATE: 2nd Attempt
Here is my controller code:
var getQuery = searchQuery.getQuery();
getQuery.then(function(query){
query = searchQuery.getQuery();
// Check if user is on main site or portal
if(location.pathname.split('/')[3] == null){
var currentProfile = location.pathname.split('/')[1];
} else {
var currentProfile = location.pathname.split('/')[3];
};
// Get the next/prev query element (if any)
console.log('6: ');
console.log(query);
var prev = query.slice(query.indexOf(currentProfile)-1)[0];
var next = query.slice(query.indexOf(currentProfile)+1)[0];
// Check if next/prev is undefined and if so, set to first/last element in query array
if(prev){
var prevProfile = prev;
} else {
var prevProfile = query.pop();
};
if(next){
var nextProfile = next;
} else {
var nextProfile = query[0];
};
$scope.goToPrev = function() {
// Check if user is on main site or portal
if(location.pathname.split('/')[3] == null){
var profileUrl = location.origin + '/' + prevProfile;
// window.location = profileUrl;
console.log(profileUrl);
} else {
var profileUrl = location.origin + '/' + location.pathname.split('/').slice(1,3).join('/') + '/' + prevProfile;
// window.location = profileUrl;
console.log(profileUrl);
}
};
$scope.goToNext = function() {
// Check if user is on main site or portal
if(location.pathname.split('/')[3] == null){
var profileUrl = location.origin + '/' + nextProfile;
// window.location = profileUrl;
console.log(profileUrl);
} else {
var profileUrl = location.origin + '/' + location.pathname.split('/').slice(1,3).join('/') + '/' + nextProfile;
// window.location = profileUrl;
console.log(profileUrl);
}
};
});
Here is my updated service:
this.getQuery = function(){
return new Promise(function(){
var query = localStorage.getItem('searchQuery');
if(query == "" || query == [""] || query == null){
var slugArray = [];
return $http.get('/companies.json')
.then(function(resp) {
if(resp && resp.data) {
for(var i in resp.data) {
var result = resp.data[i];
if(resp.data[i].name){
slugArray.push(resp.data[i].name.toLowerCase().split(' ').join('-'));
}
}
setQuery(slugArray);
} else {
resetQuery();
}
return slugArray;
}, function(err) {
resetQuery();
});
} else {
return query;
};
});
};
In Angular promises are provided through the $q service. See the documentation for more detail.
The basic outline to implement $q promise in your service is outlined below, I'll leave the detail on how to save to local storage etc to you:
this.getQuery = function(){
var deferred = $q.defer();
var query = localStorage.getItem('searchQuery');
if(query == "" || query == [""] || query == null){
$http.get('yoururl').then(function(resp) {
// assuming resp is an array, else do your parsing to get array
query = resp;
deferred.resolve(query);
}, function(err) {
query = null;
deferred.reject(err);
});
} else {
deferred.resolve(query);
};
return deferred.promise;
};
You can then use this in your controller like:
var query = null;
searchQuery.getQuery().then(function(result) {
query = result;
}, function(err) {
// Error occured
});

How to scale controllers with angular

I have some angular app, that is really easy. I've put everything into one controller, but i want to split it into multiple controllers so every controller should do action that belongs to it, not have a lot of different function of different meaning in one controller.
Here is a code:
var videoApp = angular.module('videoApp', ['videoAppFilters', 'ui.unique', 'angularUtils.directives.dirPagination']);
videoApp.controller('VideoListCtrl', function ($scope, $http, $filter) {
$scope.getFilteredResults = function (category, data, callback) {
callback = callback ||$filter('articleFilter');
$scope.videos = callback(category, data);
return $scope.videos;
};
$scope.setPageSize = function (pageSize) {
$scope.pageSize = pageSize;
return $scope.pageSize;
};
$scope.addFavorite = function (data, key) {
localStorage.setItem(key, data);
$scope.getFilteredResults(data, $scope.allData);
return alert(key + " "+ data + " was added to your favorite list.");
};
$scope.addSelectedClass = function (event) {
if($(event.target).hasClass("selected") == true)
{
$(event.target).removeClass("selected");
} else {
$(".selected").removeClass("selected");
$(event.target).addClass("selected");
}
};
$scope.formatDate = function (dateString) {
var date = new Date(parseInt(dateString));
return date.toDateString();
};
$scope.cacheLoad = function (url, allowCache) {
if(allowCache == false || localStorage.getItem(url) && (parseInt(localStorage.getItem(url + 'time')) + 20000) < (new Date().getTime()) || (!localStorage.getItem(url) )) {
$http.get(url).success(function (data) {
$scope.allData = data;
$scope.videos = data;
if(localStorage.getItem('category')) {
$scope.videos = $scope.getFilteredResults(localStorage.getItem('category'), $scope.allData);
} else {
$scope.videos = data;
}
$scope.categories = $filter('categoryFilter')(data);
if(allowCache == true && parseInt(localStorage.getItem(url + 'time')) + 20000 < (new Date().getTime() )) {
localStorage.setItem(url, JSON.stringify(data));
localStorage.setItem(url + 'time', new Date().getTime());
}
});
} else {
$scope.allData = JSON.parse(localStorage.getItem(url));
$scope.videos = JSON.parse(localStorage.getItem(url));
$scope.categories = $filter('categoryFilter')(JSON.parse(localStorage.getItem(url)));
}
};
$scope.pageSize = 12;
$scope.cacheLoad('http://academy.tutoky.com/api/json.php', true);
});
So, how to split this into multiple controllers and how to pass data between them?
You could split things out into Services, for example the following item could be a service in your code, that you then dependency inject into your controller:
Your Cache logic, This is normally something you would want to reuse so it makes sense to be a service.
You might also want to make the following item a filter or directive:
$scope.formatDate - Rather than calling this function everytime you want to format a date, it would be much easier in your html to call {{ date | formatDate }} or <div formatDate>{{ date }}</div>
You could probably strip out the pageSize too but it depends how granular you want to go.

Categories