How to show related foreign-key data in Kendo grid column - javascript

I have a kendo grid, which is controlled by an angular controller:
<div>
<kendo-grid options="mainGridOptions" k-data-source="gridData">
</kendo-grid>
</div>
UPDATE
The data is loading, but the grid isn't rendered. (I also had a term-mismatch and treated sectors as status.
"use strict";
angular.module("tenderApp")
.controller("tenderCtrl", ["$scope", "adalAuthenticationService", "tenderSvc", "$q", function ($scope, adalService, tenderSvc, $q) {
$scope.mainGridOptions = null;
$scope.gridSource = null;
$scope.statusData = null;
function loadStatusData() {
return tenderSvc.getSector()
.then(function(sector) {
$scope.sectorData = sector.data.map(function (obj) {
return {
text: obj.bezeichnung,
value: obj.id
};
});
return $scope.sectorData;
});
}
function loadGridSource(result) {
return tenderSvc.getItems()
.then(function (res) {
$scope.gridSource = res.data;
return res.data;
});
}
loadStatusData()
.then(loadGridSource)
.then(function (res) {
//both properties are available at this point
console.log($scope.gridSource);
console.log($scope.sectorData);
$scope.gridData = new kendo.data.DataSource({
transport: {
read: function (e) {
e.success($scope.gridSource);
},
//...
},
//...
});
$scope.mainGridOptions = {
toolbar: ["excel"],
dataSource: $scope.gridData,
columns: [
{ field: "sektor", title: "Sektor", values: $scope.sectorData },
{ command: ["edit"], title: "Aktionen", width: "120px" }
]
};
});
}]);
The problem is, the last call, which should populate the grid, does not work properly. The console.log calls show that the data is loaded, but the grid does not show up.

Nice one, now I learn how to do chaining from you. As for your problem, we don't need to use transport/read. Instead, we can load the data separately and set it to the grid dataSource like this. Note that, please don't put k-data-source="gridData" in your grid html attribute since you already have grid options.
HTML:
<div><kendo-grid options="mainGridOptions" k-data-source="gridData">
</kendo-grid></div>
JS:
"use strict";
angular.module("tenderApp")
.controller("tenderCtrl", ["$scope", "adalAuthenticationService", "tenderSvc", "$q", function ($scope, adalService, tenderSvc, $q) {
$scope.mainGridOptions = null;
$scope.gridSource = null;
$scope.statusData = null;
$scope.mainGridOptions = {
dataSource: new kendo.data.DataSource(),
toolbar: ["excel"],
columns: [
{ field: "sektor", title: "Sektor", values: $scope.sectorData },
{ command: ["edit"], title: "Aktionen", width: "120px" }
]
};
function loadStatusData() {
return tenderSvc.getSector()
.then(function(sector) {
$scope.sectorData = sector.data.map(function (obj) {
return {
text: obj.bezeichnung,
value: obj.id
};
});
return $scope.sectorData;
});
}
function loadGridSource(result) {
return tenderSvc.getItems()
.then(function (res) {
$scope.gridSource = res.data;
return res.data;
});
}
loadStatusData()
.then(loadGridSource)
.then(function (res) {
$scope.mainGridOptions.dataSource.data($scope.gridSource);
});
}]);

Related

Update directive in parent scope

I'm pretty new to angular js, currently, it's going well but now I have a question.
I have a template with a topnav and a contentpart. All with its own controller.
With a button I can open a "submenu" where I can choose data from the database, within the "Liquid"-section. Thats working pretty well.
Since the Topnav is rendered at the login of the page, the topnav wont be rendered again.
If I add a Liquid in the content section, I have to reload the data behind the "Liquid"-Dropdown.
That dropdown is encapsulated in a directive:
function liquidselect(Data){
return {
restrict: 'AE',
templateUrl: 'views/controls/liquid_select.html',
scope: {
selectedValues : '='
},
link: function(scope) {
},
controller: function ($scope) {
//
Data.post('ownrecipes').then(function (results) {
$scope.searchRes = results;
});
// debugger;
//$scope.searchRes = RecipeDataService.data;
$scope.disabled = undefined;
$scope.searchEnabled = false;
$scope.searchRes = [];
$scope.flavoring = {amount: {}};
$scope.updateModelValue = function (selected) {
// console.log(selected);
//
$scope.selectedValues = selected;
};
}
}
}
The communication to the server is done by a factory:
app.factory("Data", ['$http', 'toaster',
function ($http, toaster ) { // This service connects to our REST API
// var deffered = $q.defer();
var serviceBase = 'api/v1/';
var obj = {};
obj.toast = function (data) {
toaster.pop(data.status, "", data.message, 3000, 'trustedHtml');
}
obj.get = function (q) {
return $http.get(serviceBase + q).then(function (results) {
return results.data;
});
};
obj.post = function (q, object) {
return $http.post(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.put = function (q, object) {
return $http.put(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.delete = function (q) {
return $http.delete(serviceBase + q).then(function (results) {
return results.data;
});
};
return obj;
}]);
How can I update/reload the data of the directive from a child scope? Is there any chance?
Here is a plunker which showcases my problem and want I want to do:
http://plnkr.co/edit/bNANkQYZfBaS4CHH3dwX
I hope it's helpful for you :-)
Layout:
Basic Layout

How to target constructed array from within $onInit() using angular-fullstack

I'm working on a angular fullstack project which uses Babel and Angular 1.5.0.
The issue is that when I'm constructing an array (this.events = []) I cannot target this array on $onInit() where I'm supposed to populate data to be displayed on ui-calendar. I do this on this.awesomeTesting = [];
So I need to populate this.events[] array with data from $http.get('/api/calendars/') inside $onInit() but I don't understand why I cannot target the array so I can populate the data.
What am I doing wrong?
Here is my code:
'use strict';
(function() {
class MainController {
constructor($http, $scope, socket, uiCalendarConfig) {
this.$http = $http;
this.socket = socket;
this.awesomeThings = [];
this.awesomeTesting = [];
this.events = [];
this.events.splice(0, this.events.length);
this.eventSources = [this.events];
console.log(this.eventSources);
/* config object */
$scope.uiConfig = {
calendar:{
height: 450,
editable: true,
header:{
left: 'month',
center: 'title',
right: 'today prev,next'
},
dayClick: $scope.alertEventOnClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize
}
};
$scope.$on('$destroy', function() {
socket.unsyncUpdates('thing');
})
}
$onInit() {
this.$http.get('/api/things').then(response => {
this.awesomeThings = response.data;
this.socket.syncUpdates('thing', this.awesomeThings);
});
this.$http.get('/api/calendars').then(response => {
this.awesomeTesting = response.data;
this.awesomeTesting.forEach(function (objectItem) {
console.log('displays property in each object: ', objectItem.title);
this.events.push({
title: objectItem.title,
start: objectItem.start
});
});
this.socket.syncUpdates('calendar', this.awesomeTesting);
});
}
addThing() {
if (this.newThing) {
this.$http.post('/api/things', { name: this.newThing });
this.newThing = '';
}
}
deleteThing(thing) {
this.$http.delete('/api/things/' + thing._id);
}
}
angular.module('myApp')
.component('main', {
templateUrl: 'app/main/main.html',
controller: MainController
});
})();
I fixed the issue by making a for loop instead of .forEach() but I still would like to know the answer how it could be done with .forEach()?
The solution with for loop:
for (var i = 0; i < this.awesomeTesting.length; i++) {
this.events.push({
title: this.awesomeTesting[i].title,
start: this.awesomeTesting[i].start
});
}
Try to remove this.events.splice(0, this.events.length);
hope this helps.
Try This:
var that = this;
and than replace this.events -> that.events
`$onInit() {
*var that = this;*
this.$http.get('/api/things').then(response => {
this.awesomeThings = response.data;
this.socket.syncUpdates('thing', this.awesomeThings);
});
this.$http.get('/api/calendars').then(response => {
this.awesomeTesting = response.data;
this.awesomeTesting.forEach(function (objectItem) {
console.log('displays property in each object: ', objectItem.title);
*that.events.*push({
title: objectItem.title,
start: objectItem.start
});
});
this.socket.syncUpdates('calendar', this.awesomeTesting);
});
}`

how to load data before controller load?

How to get data from service before loading the view and controller. I do like that
resolve: {
getAlbum: function(albumService){
return albumService.getAlbums();
},getAtum: function(albumService){
return albumService.getAtum();
}
}
I have one service this
.factory('albumService', ['$http', '$q'],
function albumService($http, $q) {
// interface
var service = {
albums: [],
getAlbums: getAlbums,
getAtum:getAtum
};
return service;
// implementation
function getAlbums() {
var def = $q.defer();
$http.get("data.json")
.success(function(data) {
service.albums = data;
def.resolve(data);
})
.error(function() {
def.reject("Failed to get albums");
});
return def.promise;
}
function getAtum() {
var def = $q.defer();
$http.get("data.json")
.success(function(data) {
service.albums = data;
def.resolve(data);
})
.error(function() {
def.reject("Failed to get albums");
});
return def.promise;
}
})
I need to get data from service before loading this controller and view .
.controller('PlaylistsCtrl', function($scope) {
$scope.playlists = [{
title: 'Reggae',
id: 1
}, {
title: 'Chill',
id: 2
}, {
title: 'Dubstep',
id: 3
}, {
title: 'Indie',
id: 4
}, {
title: 'Rap',
id: 5
}, {
title: 'Cowbell',
id: 6
}];
})
I am getting data from two service .I need to show loader till I get data from both service.I am using this to show loader
http://ionicframework.com/docs/api/service/$ionicLoading/
Plunker
http://plnkr.co/edit/4k7fliaYQx3teVH326cD?p=info
The resolve properties are injected automatically by ui-router right after they get resolved.
.controller('PlaylistsCtrl', function(getAlbum, getAtum) {
// getAlbum and getAtum are resolved and ready to use
})
I would use albums and atum instead of getAlbum and getAtum as it is the data itself.
You use defer wrongly. $http.get is a promise itself. also, success and error are deprecated, use then instead.
return $http.get().then();
Simplest jsbin.
If you want to show loading spinner on page until its resolve. you can do something like below.
resolve: {
apiData: "albumService",
itemDetailsData: function($q, apiData) {
console.log("Spinner on :")
var item = apiData.getAlbums();
if (item) {
console.log("Spinner Off :")
return $q.when(item);
} else {
return $q.reject();
}
}
}
In your controller you can inject itemDetailsData as a dependency.
Hope this helps

Scope of Datas not updating after a $http AngularJS

I can't understand why it does not update the $scope.user_free_status when I set a user free but when I unset the parameter it works perfectly. I need to reload page in one case and not the other...
The datas fetched are stored in the localstorage.
Here is the code:
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: 'InitialCtrl',
resolve: {
theUserFreeStatus: function(DataService) {
return DataService.getUserFreeStatus();
}
}
})
Controller:
.controller('InitialCtrl', function($scope, $state, DataService ,FreeService, SharedService, theUserFreeStatus) {
// Showing set free but not unset or not
if (FreeService.isSetFree()) {
$scope.showSetFree = false;
$scope.showUnSetFree = true;
} else {
$scope.showSetFree = true;
$scope.showUnSetFree = true;
}
// Show the Free status set when arriving on page/app
$scope.user_free_status = theUserFreeStatus;
// Set user as Free
$scope.setFree = function(activity, tags) {
FreeService.setFree(activity, tags).success(function() {
console.log($scope.user_free_status);
$scope.user_free_status = DataService.getUserFreeStatus();
console.log($scope.user_free_status);
$scope.showSetFree = false;
$scope.showUnSetFree = true;
SharedService.goHome();
})
}
//// Free status unset
$scope.unsetFree = function() {
FreeService.unsetFree().success(function() {
$scope.user_free_status = [];
$scope.showSetFree = true;
$scope.showUnSetFree = false;
SharedService.goHome();
});
};
})
The services:
.factory('FreeService', function(WebService, $localstorage, $ionicPopup, DataService, $sanitize, CSRF_TOKEN) {
var cacheFreeStatus = function(free_status) {
$localstorage.setObject('user_free_status', free_status)
};
var uncacheFreeStatus = function() {
$localstorage.unset('user_free_status')
}
return {
setFree: function(activity, tags) {
var status = { SOME STUFF BLABLABLA };
var setFree = WebService.post('setstatus/', sanitizeStatus(status));
setFree.success(function(response) {
console.log('available' + response.flash);
cacheFreeStatus(response.status_response);
})
setFree.error(freeError)
return setFree;
},
unsetFree: function() {
var details = {OTHER STUFF};
var unsetFree = WebService.post('unsetstatus/', details);
unsetFree.success(function(response) {
console.log('unset ' + response.flash);
uncacheFreeStatus(response.status_response);
})
unsetFree.error(freeError)
return unsetFree;
},
isSetFree: function() {
return $localstorage.get('user_free_status');
}
}
})
.service('DataService', function($q, $localstorage) {
return {
activities: $localstorage.getObject('activities'),
getActivities: function() {
return this.activities;
},
user_free_status: $localstorage.getObject('user_free_status'),
getUserFreeStatus: function() {
return this.user_free_status;
}
}
})
* Local Storage Service
------------------------------------------------------*/
.factory('$localstorage', ['$window', function($window) {
return {
set: function(key, value) {
$window.localStorage[key] = value;
},
unset: function(key) {
localStorage.removeItem(key);
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '{}');
}
}
}])
When setting the user's status, the console returns that the $http call worked but an empty array for the $scope variable I try to set. Once I reload the page I can see the updates displayed. If I unset the user's status, the $scope is properly updated without need to reload the page.
The Webservice is just the $http call.
What am I missing here to have the $scope.user_free_status updated correctly without having to reload the page??
Thanks for your time!
Your data service is injected as service but you have not appended the functions to this.rather you have returned it as part of literal like u do in factory

angularjs ng-repeat not updating view when new data comes in

I have a service which will make a call to the server and returns the data. I am binding service to a variable on scope.
Example:
Let the service be DataModelService
in the controller : $scope.data = DataModelService
in the view <div ng-repeat="value in data.persons">{{value.name}}</div>
My Code :
This is how my code looks like:
/**DataModelService**/
factory('DataModelService', [
'DataService',
function (DataService) {
var service;
service = {
changeState: function (params) {
DataService.changePersonState(params)
.then(function (response) {
service.loadData(response.data);
});
},
loadData: function (responseData) {
service.persons = responseData.persons;
}
}
return service;
}
]);
/**DataService**/
factory('DataService', ['$http',
function ($http) {
return {
changePersonState: function (params) {
return $http.post("url", params);
}
}
}
]);
/**DataController**/
.controller('DataController', ['DataModelService',
function (DataModelService) {
$scope.data = DataModelService;
}
]);
/view/
<div ng-repeat = "person in data.persons" >{{person.name}} </div>
On the view I am doing a ng-repeat on a key in data i.e. ng-repeat="value in data.persons"
and also I have an option to change the state of person to active or inactive, so whenver i make a change to the state of the person, a call is sent to the server and data is set into the Service and as it is binded to the view, it should automatically update the data. But whats happening in my case, ng-repeat is not removing old data and instead it is appending new data to the old data.
For me its not good approach to write promise callback (then) into service. Because in your case, DataModelService returns data with some delay but not promise. And we don't know when.
So the way to make it work to add basic $timeout and fetch data from service by using other method.
So my suggestion is Demo
and your fixed example: Demo2
If we will take your example, it should be like:
JS
var fessmodule = angular.module('myModule', ['ngResource']);
fessmodule.controller('fessCntrl', function ($scope, DataModelService, $timeout) {
$scope.alertSwap = function () {
DataModelService.changeState('ff');
$timeout(function(){
$scope.data = DataModelService.getResponse();
}, 10);
}
});
fessmodule.$inject = ['$scope', 'Data', '$timeout'];
/**DataModelService**/
fessmodule.factory('DataModelService', [ 'DataService',function (DataService) {
var value = [];
var service = {
changeState: function (params) {
DataService.changePersonState(params)
.then(function (response) {
value = response.persons;
});
},
getResponse : function(){
return value;
}
}
return service;
}
]);
/**DataService**/
fessmodule.factory('DataService', ['$q',function ($q) {
var data = { // dummy
persons: [{
name: "Bob"
}, {
name: "Mark"
}, {
name: "Kelly"
}]
};
var factory = {
changePersonState: function (selectedSubject) {
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
} //function
]);

Categories