For example, I have such request to my server. As a response, I will get an array of objects with parameters: id, name and position. All of these loads into a table. How can I manipulate with an array $scope.employees if i will decide to change it later?
An answer from server is:
data = [{"id":1,"name":"Jack","position":"City guard"},{"id":2,"name":"Jim","position":"Sheriff"},{"id":4,"name":"Jack","position":"Cruel genius"},{"id":7,"name":"Guy","position":"Manager"}]
And how to be sure, that request is already posted into a table, so i can perform some later operations?
angular
.module('MyApp', [])
.controller('MyController', ['$scope', '$http', MyController]);
function MyController ($scope, $http) {
$http.get("/servlet").success(function(data){
$scope.employees = data;
});
}
function otherOperation () {
$scope.employees.push({
id : 5,
name : "John",
position : "Manager"
});
}
HTML code:
<div id="content" ng-controller='MyController'>
<table id="table">
<tr>
<th> ID </th>
<th> Name </th>
<th> Position </th>
</tr>
<tr ng-repeat="employee in employees">
<td>{{employee.id}}</td>
<td>{{employee.name}}</td>
<td>{{employee.position}}</td>
</tr>
</table>
<button ng-click="otherOperation"> Button </button>
</div>
The otherOperation method should be nested inside MyController, like this:
angular
.module('MyApp', [])
.controller('MyController', ['$scope', '$http', MyController]);
function MyController ($scope, $http) {
function otherOperation () {
$scope.employees.push({
id : 5,
name : "John",
position : "Manager"
});
}
$http.get("/servlet").success(function(data){
$scope.employees = data;
});
}
You could also pass the $scope as a parameter, like this:
angular
.module('MyApp', [])
.controller('MyController', ['$scope', '$http', MyController]);
function MyController ($scope, $http) {
$http.get("/servlet").success(function(data){
$scope.employees = data;
});
otherOperation($scope);
}
function otherOperation ($scope) {
$scope.employees.push({
id : 5,
name : "John",
position : "Manager"
});
}
Related
I have a controller in the provided module that uses data from either a JSON file or an API call. The JSON file version GetActionItems2() works perfectly. Unfortunately, I cannot get the GetActionItems() to work just like its counterpart function (the JSON version). I am using deferred promises and Angular DataTables. No errors in console, but my table has no data in the page.
How do I resolve this?
Controller
angular.module('Action').controller('ActionController', ['$http', '$resource', '$scope', '$state', '$timeout', '$q', 'DTOptionsBuilder', function($http, $resource, $scope, $state, $timeout, $q, DTOptionsBuilder){
$scope.actionitems = {};
function GetActionItems2()
{
return $resource('actionitems.json').query().$promise;
}
function GetActionItems() {
var defer = $q.defer();
$http.get('api/actionitems')
.then(function(response){
defer.resolve(response);
});
return defer.promise;
}
$scope.init = function(){
var vm = this;
vm.dtOptions = DTOptionsBuilder.fromFnPromise(function() {
var defer = $q.defer();
GetActionItems().then(function(result) {
$scope.actionitems = result;
defer.resolve(result);
});
return defer.promise;
})
.withPaginationType('full_numbers')
//.withOption('drawCallback', reload)
.withDisplayLength(10)
//.withOption('order', [1, 'desc'])
.withOption('scrollY', 500)
.withOption('scrollX', '100%')
.withDOM('lftrpi')
.withScroller();
}
}]);
Template
<div ng-init="init()" ng-controller="ActionController">
ActionItems
<table id="actionitems" class="row-border hover action" datatable="" dt-options="dtOptions">
<thead>
<tr>
<th>
ID
</th>
<th>
Action Item Title
</th>
<th>
Criticality
</th>
<th>
Assignor
</th>
<th>
Owner
</th>
<th>
Alt Owner
</th>
<th>
Approver
</th>
<th>
Assigned Date
</th>
<th>
DueDate
</th>
<th>
ECD
</th>
<th>
Completion Date
</th>
<th>
Closed Date
</th>
<th>
Team
</th>
<th>
Meeting
</th>
<th>
Phase
</th>
<th>
Source
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="actionitem in actionitems">
<td>{{actionitem.ActionItemID}}</td>
<td>{{actionitem.Title}}</td>
<td>{{actionitem.Criticality}}</td>
<td>{{actionitem.Assignor}}</td>
<td>{{actionitem.Owner}}</td>
<td>{{actionitem.AltOwner}}</td>
<td>{{actionitem.Approver}}</td>
<td>{{actionitem.AssignedDate}}</td>
<td>{{actionitem.DueDate}}</td>
<td>{{actionitem.ECD}}</td>
<td>{{actionitem.CompletionDate}}</td>
<td>{{actionitem.ClosedDate}}</td>
</tbody>
</table>
</div>
Returning $http.get('api/actionitems').then(function(result) to fromFnPromise with an embedded return result.data inside of function(result) resolved the issue and avoided usage of the deferred Anti-pattern.
$scope.init = function() {
var vm = this;
vm.dtOptions = DTOptionsBuilder.fromFnPromise(function() {
return $http.get('api/actionitems').then(function(result) {
$.each(result.data, function(key, actionitem) {
result.data[key] = [
actionitem.actionitemid,
actionitem.actionitemtitle,
actionitem.criticality,
actionitem.assignor,
actionitem.owner,
actionitem.altowner,
actionitem.approver,
actionitem.assigneddate,
actionitem.duedate,
actionitem.ecd,
actionitem.completiondate,
actionitem.closeddate
];
});
$scope.actionitems = result.data;
return result.data;
});
})
.withPaginationType('full_numbers')
//.withOption('drawCallback', reload)
.withDisplayLength(10)
//.withOption('order', [1, 'desc'])
.withOption('scrollY', 500)
.withOption('scrollX', '100%')
.withDOM('lftrpi')
.withScroller();
}
If this asynchronous processing comes from a third party, you may need to manually trigger a data update for that controller.
// ...
$scope.init = function(){
var vm = this;
vm.dtOptions = DTOptionsBuilder.fromFnPromise(function() {
var defer = $q.defer();
GetActionItems().then(function(result) {
$scope.actionitems = result;
// here trigger a data update
$scope.$digest();
defer.resolve(result);
});
return defer.promise;
})
// ...
The $digest method is to manually trigger the change detection of the controller.
SEE EDIT BELOW
My initial solution was a two step process to get data into my table.
I introduced a custom apply function then a getRes function which then populated array of actionitems with individual actionitems with only an array of values to be sent off to datatables and asign to a $scope.acionitems. Otherwise I would get an alert from datatables that regarding the format of each item being in JSON format with corresponding keys.
angular.module('Action').controller('ActionController', ['$http', '$resource', '$scope', '$state', '$timeout', '$q', 'DTOptionsBuilder', function($http, $resource, $scope, $state, $timeout, $q, DTOptionsBuilder){
$scope.actionitems = {};
function GetActionItems2()
{
return $resource('actionitems.json').query().$promise;
}
function GetActionItems() {
var defer = $q.defer();
$http.get('api/actionitems')
.then(function(response){
defer.resolve(response);
});
return defer.promise;
}
var getRes = function(res){
$.each(res, function(key, actionitem){
res[key] = [
actionitem.actionitemid,
actionitem.actionitemtitle,
actionitem.criticality,
actionitem.assignor,
actionitem.owner,
actionitem.altowner,
actionitem.approver,
actionitem.assigneddate,
actionitem.duedate,
actionitem.ecd,
actionitem.completiondate,
actionitem.closeddate
];
});
$scope.actionitems = res;
}
function apply(scope, fn, res) {
(scope.$$phase || scope.$root.$$phase) ?
fn(res) :
scope.$apply(fn(res));
}
$scope.init = function(){
var vm = this;
vm.dtOptions = DTOptionsBuilder.fromFnPromise(function() {
var defer = $q.defer();
GetActionItems().then(function(result){
apply($scope, getRes, result.data);
defer.resolve(result.data);
});
return defer.promise;
})
.withPaginationType('full_numbers')
//.withOption('drawCallback', reload)
.withDisplayLength(10)
//.withOption('order', [1, 'desc'])
.withOption('scrollY', 500)
.withOption('scrollX', '100%')
.withDOM('lftrpi')
.withScroller();
}
}]);
EDIT
I simplified the code and used a resolve on the actual data attribute of result not object itself which produced data in my table.
The following modification based on my Anti-Pattern usage is the best I could get so far to achieve the same results.
angular.module('Action').controller('ActionController', ['$http', '$resource', '$scope', '$state', '$timeout', '$q', 'DTOptionsBuilder', function($http, $resource, $scope, $state, $timeout, $q, DTOptionsBuilder){
$scope.actionitems = {};
function GetActionItems2()
{
return $resource('actionitems.json').query().$promise;
}
function GetActionItems() {
var defer = $q.defer();
var res = $http.get('api/actionitems').then(function(result){
var data = result.data;
$.each(data, function(key, actionitem){
data[key] = [
actionitem.actionitemid,
actionitem.actionitemtitle,
actionitem.criticality,
actionitem.assignor,
actionitem.owner,
actionitem.altowner,
actionitem.approver,
actionitem.assigneddate,
actionitem.duedate,
actionitem.ecd,
actionitem.completiondate,
actionitem.closeddate
];
});
$scope.actionitems = data;
defer.resolve(data);
});
return defer.promise;
}
$scope.init = function(){
var vm = this;
vm.dtOptions = DTOptionsBuilder
.fromFnPromise(GetActionItems)
.withPaginationType('full_numbers')
//.withOption('drawCallback', reload)
.withDisplayLength(10)
//.withOption('order', [1, 'desc'])
.withOption('scrollY', 500)
.withOption('scrollX', '100%')
.withDOM('lftrpi')
.withScroller();
}
}]);
This is cshtml contents:
#model MBOS.DTO.ViewModel.Others.ReportTemplateViewModel<MBOS.DTO.ViewModel.BranchBOCAAnalysis>
#if (Model.IncludeTableHeader)
{<thead>
<tr class="no-borders">
<th>No.</th>
<th>Branch</th>
<th>Assessor</th>
<th>Rating</th>
</tr>
</thead>
}
#foreach (var row in Model.Models)
{
<tr>
<td>#row.Id</td>
<td>#row.Branch</td>
<td>#row.Assessor</td>
<td>#row.Rating.FormatDouble() </td>
</tr>
}
This is AngularJs Controller:
(function () {
'use strict';
angular.module("app.branchAnalysis", ["app.base.report"])
.controller('branchAnalysisCtrl', ['$scope', '$http',
'appStore', '$controller', '$routeParams', 'Restangular', 'toaster',
'$location', '$q', '$filter',
function ($scope, $http, appStore, $controller, $routeParams, Restangular, toaster, $location, $q, $filter) {
$scope.RatingDetail = function () {
debugger;
restangular.one("dashboard/" + (type === 'b' ? 'boca' : 'aoca') + "/assessment/rating/" + assessment.BranchId + "/" + assessment.AssessmentMonth).get().then(function (response) {
if (type === 'b')
$scope.bocaStatusPieViewModel.RatingItems = response.plain();
else
$scope.aocaStatusPieViewModel.RatingItems = response.plain();
});
}
}]);
})();
I am trying to call RatingDetail() function from the href link as mentioned in the above cshtml.
I tried with ng-click but also not worked. I need some good and working examples. I am waiting for exact solutions.
You mention you tried to get it working with ng-click but it didn't work, what issue did you have?
See primitive JSFiddle example with working ng-click http://jsfiddle.net/Lvc0u55v/12116/
I have school task.
We have a HTML code like this:
<html ng-app="myTest">
<head><script type="text/javascript" src="../myScript.js"></script>
</head>
<body id="tst" class="textpage" ng-controller="TestController as testcon">
<form class="" id="frm" ng-submit="doStuff()">
<div class="form-group">
{{testinfo}}
</div>
<div class="form-group">
<button type="submit" id="sbtn" name="sbtn">testSubmit</button>
</div>
</form>
</body>
</html>
Content of javascript with name myScript.js is this:
var tester = angular.module('myTest', ['ui.mask']);
tester.controller('TestController', ['$scope', '$http', '$location', '$window', function ($scope, $http, $location, $window) {
$scope.doStuff = function () {
{
$scope.testinfo = 'unknown value';
};
};
}
]);
I have option to add new javascript.
But I am not possible to get value from $scope.testninfo.
I cannot edit existing JavaScript and cannot edit HTML file. I can just add new javascript.
Is there option how to get value from $scope.testinfo in another javascript?
Thanks.
You can use broadcast
From controller 1 we broadcast an event
$scope.$broadcast('myEvent',anyData);
controller 2 will receive our event
$scope.$on('myEvent', function(event,anyData) {
//code for controller 2
});
here anyData represent your object to be passed
Use ng-model.
<div class="form-group">
<input type="text" ng-model="testinfo">
</div>
I dont think it is possible without appending the existing javascript/html. Because the $scope of the TestController cannot be accessed from another controller (file).
If you COULD append the HTML you could use the $rootscope, in that way the value, which is set by the TestController is accessible from another controller. Or you can add a Global app value. I created a fiddle which show the two options: https://jsfiddle.net/Appiez/wnyb9pxc/2/
var tester = angular.module('myTest', []);
tester.value('globalVar', { value: '' });
tester.controller('TestController', ['$rootScope', '$scope', '$http', '$location', '$window', 'globalVar', function ($rootScope, $scope, $http, $location, $window, globalVar) {
$scope.doStuff = function () {
{
$rootScope.testinfo = 'this is the new value';
globalVar.value = 'a global value';
};
};
}
]);
tester.controller('TestController2', ['$rootScope', '$scope', 'globalVar', function ($rootScope, $scope, globalVar) {
$scope.doStuff2 = function () {
{
alert($rootScope.testinfo);
alert(globalVar.value);
};
};
}
]);
This is what services are for in angular. They ferry data across controllers. You can use NG's $broadcast to publish events that contain data, but Providers, Services, and Factories are built to solve this.
angular.module('krs', [])
.controller('OneCtrl', function($scope, data){
$scope.theData = data.getData();
})
.controller('TwoCtrl', function($scope, data){
$scope.theData = data.getData();
})
.service('data', function(){
return {
getData: function(){
return ["Foo", "Bar"];
}
}
});
Here's a fiddle to help get you into the swing of things. Good luck in school!
I set the $stateParam by getting a cell value from a table:
$scope.tableClick = function() {
var tr = $('#Table_1').find('tr');
var id = $(event.target).parent().find("td:first").text();
$stateParams.engineId == id;
$state.go('engineselection');
}
When I stop the debug at this point. It gives me the engineId value.
This is the router part that I use:
$stateProvider.state('engineselection', {
url : '/engineselection:engineId',
templateUrl : 'assets/views/engineselection.html',
controller : 'EngineSelectionCtrl'
})
This is what happens in the controller:
controllers.controller("EngineSelectionCtrl",
["$scope", "$rootScope", "directiveBinder", '$timeout', '$stateParams', '$resource', '$location', 'rtmService', '$state',
function($scope, $rootScope, directiveBinder, $timeout, $stateParams, $resource, $location, myService, $state) {
myService.loadViewWithEngine(function(id, data) {
$scope.views = data;
$scope.$apply();
$('#loadingViews').spin(false);
});
When I stop here before the function and type console $stateParams, it tells me that I have a state parameter named 'engineId' but it is undefined. What should I do to pass the parameter to the controller with its value?
Worked after I have changed $state.go call like this:
$state.go('viewselection', {engineProgramId: id});
So I am experimenting with Angular. I created the following module.
var archiveModule = angular.module('archiveModule', ['ngResource']);
archiveModule.factory('Archive', ['$resource',
function($resource) {
return $resource('/data/archive/:doc.json', {}, {
query: { method:'GET', params:{ doc: undefined }, isArray:true }
});
}]);
archiveModule.controller('ArchiveControl', ['$scope', '$http', 'Archive',
function ($scope, Archive) {
$scope.items = Archive.query();
$scope.orderProp = 'name';
}]);
My template everything happens within:
<div class="container" ng-app="archiveModule">
<div ng-controller="ArchiveControl">
I include the angular scripts at the bottom of my page:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-resource.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-route.js"></script>
And Chrome reports TypeError: undefined is not a function, and it goes back to the line $scope.items = Archive.query();.
According to http://docs.angularjs.org/api/ngResource.$resource, query is part of $resource and I modeled my resource off http://docs.angularjs.org/tutorial/step_11 I'm not sure what's going wrong here.
Your parameters don't line up with the dependencies that are declared. It's injecting $http into Archive...
archiveModule.controller('ArchiveControl', ['$scope', '$http', 'Archive',
function ($scope, Archive) {
Remove '$http' and it should work...
archiveModule.controller('ArchiveControl', ['$scope', 'Archive',
function ($scope, Archive) {
$scope.items = Archive.query();
$scope.orderProp = 'name';
}]);