Enrich angularjs json data with additional view logic properties - javascript

When I load my json data from the server I need to have additional view only properties on json data. But thats not possible.
Then I thought about creating angularjs models from factories like:
'use strict';
angular.module('TGB').factory('TestViewModel', function () {
function TestViewModel(test) {
this.id = test.id;
this.schoolclassCode = test.schoolclassCode;
this.testType = test.type;
this.creationDate = test.date;
this.number = test.number;
this.isExpanded = false;
}
return (TestViewModel);
});
Where do you create these viewmodels in angular?
At the moment I have this method in my Controller , call it there and assign the result to $scope.testViewModels = toTestListViewModel(tests)
function toTestListViewModel(tests)
{
var testListViewModel = [];
for (var i = 0; i < tests.length; i++) {
var testViewModel = new TestViewModel(tests[i]);
testListViewModel.push(testViewModel);
}
return testListViewModel;
}

Controller is a proper place to create your 'view model' that can be accessed using $scope.
.controller('sampleCtrl', function ($scope, testViewModel) {
$scope.vM = testViewModel;
}

Related

How to share a $scope object between multiple controllers

I am facing problem while sharing a $scope object between 2 controllers.
In controller 'IssueBookCtrl',I am updating the books object element value like this.
$scope.books[i].issued = true;
Then I am using $emit service to share the $scope object with controller 'BookListCtrl_Librarian'.
$scope.$emit('update_parent_controller', $scope.books);
But when I run the view which is using the controller 'BookListCtrl_Librarian',i don't see the updated object.
controller.js
Controllers.controller('BookListCtrl_Librarian', ['$scope','$http','$location','$rootScope','BookData',
function ($scope, $http ,$location, $rootScope , BookData) {
$http.get('data/books.json').success(function(data) {
if($rootScope.books==='undefined'){
$rootScope.books = BookData.getData();
}
$scope.books = data;
});
$scope.options = ['bookId', 'cost'];
$scope.$on("update_parent_controller", function(event, books){
$scope.books = books;
});
$scope.issue = function(bookId) {
for (var i = 0, len = $scope.books.length; i < len; i++) {
if ($scope.books[i].bookId == bookId) {
$rootScope.book = $scope.books[i];
break;
}
}
$location.path('/issue/'+bookId);
}
$scope.return = function (bookId) {
for (var i = 0, len = $scope.books.length; i < len; i++) {
if ($scope.books[i].bookId == bookId) {
$rootScope.book = $scope.books[i];
break;
}
}
$location.path('/return/'+bookId);
}
$scope.backToLogin = function() {
$location.path("/main");
}
}]);
Controllers.controller('IssueBookCtrl', ['$scope','$rootScope','$http','$routeParams','$location',
function ($scope,$rootScope, $http, $routeParams, $location) {
var Id=$routeParams.bookId;
$http.get('data/books.json').success(function(data) {
$scope.books = data;
});
$scope.issue = function(Id) {
alert("issued");
for (var i = 0, len = $scope.books.length; i < len; i++) {
if ($scope.books[i].bookId === Id) {
$scope.books[i].issued = true;
$scope.$emit('update_parent_controller', $scope.books);
$location.path('/home/librarian');
break;
}
}
}
}]);
Please guide me,any help is much appreciated.
Thanks
hi u have to use rootscope instead of scope emit
$rootScope.$emit('update_parent_controller', $scope.books);
and in other controler
$rootScope.$on('update_parent_controller', function(event, books){
$scope.books = books;
});
You could try forcing a digest after altering a model:
$scope.$apply();
But I would recommended that you build a Books service to hold those shared models and logic. You can learn about creating your own custom services here.
Or you could nest your controllers (put one inside the other) so that the inner controller can reference the outer controller's models by using $parent variable.
By using either you should not have any problems with object updating as AngularJs runs dirty-checks when scope variables are changed.

Unable to pass argument to http get request in angular js

I'm pretty much new in angular js. What I am trying to do is pass an integer argument to http get request in my controller. This is how my sample code looks like.
(function() {
angular
.module('myApp.directory', [])
.factory('NewsService', function($http)
{
return {
getallnews: function() {
return $http.get('get_all_news_feed.php?page='+pageNumber);
}
};
})
.factory('NewsFeed', function(directoryService) {
var NewsFeed = function() {
this.items = [];
this.busy = false;
this.pageNumber = 1;
};
NewsFeed.prototype.nextPage = function() {
if (this.busy) return;
this.busy = true;
NewsService.getallnews().success(function(data) {
var itemData = data;
for (var i = 0; i < itemData.length; i++) {
this.items.push(itemData[i]);
}
this.pageNumber++;
this.busy = false;
}.bind(this));
};
return NewsFeed;
})
.controller('MyController', function(NewsFeed, NewsService) {
var inst = this;
inst.news = new NewsFeed();
});
})();
I am building a news feed app. News is fetched from get_all_news_feed.php page and I want to pass a parameter pageNumber to it. This is while implementing infinte scrolling in angular.
I am getting undefined error. Any ideas?
Modify the factory method to accept pageNumber as parameter
getallnews: function(pageNumber) {
return $http.get('get_all_news_feed.php?page='+pageNumber);
}
Pass it when calling the method
NewsService.getallnews(this.pageNumber)

angularJS: Dynamic header sorting not working

I am trying to implement a solution to sort a table by clicking its headers, using AngularJS.
I found a good example after doing a Google search: https://scotch.io/tutorials/sort-and-filter-a-table-using-angular
I am able to see the up and down arrows, but the table does not sort when I click them.
I think the problem resides in how the JSON object is formatted in my situation. I have not been able to figure it out, and I am hoping that with the information that I am providing on this post, I can get some help to understand what I am doing incorrectly.
Here is a copy of the JavaScript:
(function (define, angular) {
'use strict';
define(function () {
var opportunityController = function ($scope, Metadata, Factory) {
var vm = this;
//set the default sort type
vm.sortType = 'Products';
//set the default sort order
vm.sortReverse = false;
Factory.Data(caller.sp, caller.filter).then(function (payload) {
var data = angular.fromJson(payload.data).Table;
ProcessData(data);
});
function ProcessData(data) {
if (angular.isDefined(data)) {
var counter = 0;
vm.products = [];
vm.productsSet = FindByAsObjectArray(function (x) {
return (x.TypeName == "Product");
}, data);
for (var index = 0, length = vm.productsSet.length; index < length; index++) {
vm.products[index] = {
data: vm.productsSet[index]
};
}
}
}
};
return ['$scope','Metadata','Factory',opportunityController];
});
})(define, angular);
I got it to work, final version: https://jsfiddle.net/itortu/nhhppf53/
Many thanks.
You are using controllerAs
ng-controller="Company:OpportunityController as opportunity"
therefor you have to reference sortType and sortReverse in your ng-click like so:
ng-click="opportunity.sortType = 'Products'; opportunity.sortReverse = !opportunity.sortReverse"

Dynamically set data on Angular-chart.js

To be honest I am a bit new to angularjs, so this may be problem with my fundamental understanding of angular, rather than angular-charts.
I have two controllers (PieItemsCtrl and PieCtrl) and I would like to communicate between them by using a factory service (called pieItems)
On the one hand the pieItems works as designed in the PieItemsCtrl.
ie:
$scope.slices = pieItems.list();
Whenever something changes in the pieItems service (ie another element is added), then the HTML is automatically updated via a repeater :
<div ng-repeat="(key, val) in slices">
However in the PieCtrl I have this line, and i would expect the pie chart to update automatically :
$scope.labels = pieItems.labelsItems();
$scope.data = pieItems.data();
It seems to set these data values upon loading/initialisation of the PieCtrl and that's it. Whenever the pieItems data changes these scope values are not updated.
The source of the two controller and factory object are below. And I also made an unworkable fiddle, incase that helps
PieItemsCtrl :
app.controller('PieItemsCtrl', function($scope, $http, $rootScope, pieItems) {
$scope.slices = pieItems.list();
$scope.buttonClick = function($event) {
pieItems.add(
{
Name: $scope.newSliceName,
Percent: $scope.newSlicePercent,
Color: $scope.newSliceColor
}
)
}
$scope.deleteClick = function(item, $event) {
pieItems.delete(item);
}
}
)
PieCtrl :
app.controller("PieCtrl", function ($scope, $timeout, pieItems) {
$scope.labels = pieItems.labelsItems();
$scope.data = pieItems.data();
});
pieItems :
app.factory('pieItems', function() {
var items = [];
var itemsService = {};
itemsService.add = function(item) {
items.push(item);
};
itemsService.delete = function(item) {
for (i = 0; i < items.length; i++) {
if (items[i].Name === item.Name) {
items.splice(i, 1);
}
}
};
itemsService.list = function() {
return items;
};
itemsService.labelsItems = function() {
var a = ['x', 'y'];
for (i = 0; i < items.length; i++) {
a.push(items[i].Name);
}
return a;
};
itemsService.data = function() {
var a = [50,50];
for (i = 0; i < items.length; i++) {
a.push(items[i].Percent);
}
return a;
};
return itemsService;
});
The controller doesn't notice when the value in your factory changes. To include your item-Array in an Angular digest-cycle, tell Angular to $watch that Array.
If you don't want to expose the Array, create a getter:
itemsService.get = function() { return items; }
Then you can include that getter in your $watch expression in your controller:
$scope.$watch(getItems, watcherFunction, true);
function getItems() {
return pieItems.get();
}
The getItems-Function gets called on digest cycle and fires the watcherFunction if the value changed and has the newData as argument. true as 3rd argument creates a deep watch.
function watcherFunction(newData) {
console.log(newData);
// do sth if array was changed
}
For more complex objets, you can use a $watchCollection.

call a controller from getView()

how do get a controller of a view
var c = Alloy.createController('win', activeTab);
c = c.getView();
Wins.push(c);
in controller win i have function
exports.fun = function() {
};
after getting the win from controller which is the view how do i call this function from a view i need controller to call the function
for ( i = 0; i < Wins.length; i++) {
Wins[i].fun();
}
Wins[i] is a View how do i get a controller of this view so that i can call the function fun()
dont push the window, push the controller
// this is a bad name for a controller...
var controller = Alloy.createController('win', activeTab);
var view = controller.getView();
// save the controller to a list of global controllers
Alloy.Globals.Controllers = Alloy.Globals.Controllers || {};
Alloy.Globals.Controllers['aController'] = controller;
// loop through all controller and execute func if it exists
for ( var i in Alloy.Globals.Controllers) {
Alloy.Globals.Controllers[i].fun && Alloy.Globals.Controllers[i].fun();
}

Categories