Angularjs: accessing scope variable array and calculating average - javascript

sorry if the question is a little abstract from the title. I will try to explain it here and supply a Gist with relevant code.
I have a JSON api which I grab through AngularJS. This is basically a project which has several tasks. I want to go through the tasks in my $scope.projects variable (in my projects controller) and get all the 'progress' values in each task. Then I want calculate the average of them to give the overall progress for the project itself and assign it to a $scope variable to be used in my template.
I cant seem to get access to the tasks array no matter what I try and I have no idea why. So i thought asking here for some advice might be a good option. Any help would be greatly appreciated.
Gist: https://gist.github.com/Tasemu/8002741
JS
App.controller('ProjectCtrl', ['$scope', 'Project', 'Task', '$routeParams', '$location', function($scope, Project, Task, $routeParams, $location) {
$scope.updateProjects = function() {
if (!$routeParams.id) {
Project.query(function(data) {
$scope.projects = data;
});
} else {
$scope.projects = Project.get({id: $routeParams.id})
}
};
$scope.deleteProject = function(project) {
Project.delete({id: project.id}, function() {
$scope.updateProjects({id: project.id});
$location.path('/');
});
};
$scope.deleteTask = function(task) {
Task.delete({id: task.id}, function() {
$scope.updateProjects({id: task.id});
});
};
$scope.updateProject = function(formData) {
$scope.projects.name = formData.name;
$scope.projects.description = formData.description;
$scope.projects.client = formData.client;
$scope.projects.due = formData.due;
$scope.projects.$update({id: formData.id}, function() {
$location.path('/');
});
};
$scope.saveProject = function(project) {
Project.save({}, project, function() {
$location.path('/');
});
};
$scope.updateProjects();
$scope.progs = [];
for (var i = 0; i > $scope.projects.tasks.length; i++) {
progs.push($scope.projects.tasks.array[i].progress);
};
}]);
JSON
{
id: 1,
name: "Project 1",
description: "this project",
client: "monty",
due: "2013-12-15",
tasks: [
{
id: 2,
name: "Task 2",
progress: 22,
project_id: 1,
created_at: "2013-12-17T03:08:53.849Z",
updated_at: "2013-12-17T05:06:31.602Z"
},
{
id: 1,
name: "Task 1",
progress: 75,
project_id: 1,
created_at: "2013-12-17T03:08:53.845Z",
updated_at: "2013-12-17T05:25:50.405Z"
}
],
created_at: "2013-12-17T03:08:53.719Z",
updated_at: "2013-12-17T06:57:52.699Z"
}
JS
App.factory('Project', function($resource) {
return $resource(
'/api/v1/projects/:id.json',
{id: '#id'},
{
update: {
method: 'PUT',
params: { id: '#id' },
isArray: false
}
}
);
});
If you need any more information please don't hesitate to ask!

You have to delay the progress calculation (line 46 to 48 in project_controller.js) until your data is fully loaded. Extract the calculation into a new method and call this new method in the callback on line 6 and in a new callback you have to create at line 9.

You are trying to access project.tasks before it is ready. I suggest you wrap the calculation in a function and call it in the success callback when retrieving/updating projects.
$scope.updateProjects = function() {
if (!$routeParams.id) {
Project.query(function(data) {
$scope.projects = data;
$scope.calculateTasks();
});
} else {
$scope.projects = Project.get({id: $routeParams.id})
}
};
...
$scope.calculateTasks = function () {
$scope.progs = [];
for (var i = 0; i > $scope.projects.tasks.length; i++) {
$scope.progs.push($scope.projects.tasks.array[i].progress);
};
}
$scope.updateProjects();

Related

How can we pass current date-time to a angularjs function in a HTML page?

I am trying to get present date and pass it to the function - same-or-earlier-than But in the run-time, it does not pass date value to this class. Below is my html code. I am trying to get date from javascript and printing it for test.
the date is printed, but when passing it to the function, it doesnt work.
<div class="row">
<div class="hh-dock-page-view panel">
<div class="panel-body">
<div class="container">
<h2 class="hh-page-header">Issue Detail</h2>
<h3 class="hh-action-heading"><span ng-hide="ctrl.readOnly">Edit </span>Details - {{ctrl.returnCurDate()}} - {{ctrl.issue.issue_date}}"</h3>
<hh-model-form name="issueForm" model="ctrl.issue" page-controller="ctrl" submit-success="ctrl.submitSuccess" hide-actions="ctrl.readOnly">
<h2 class="hh-page-header extra-margin">{{modelFormCtrl.model.provider_name_spec_prac}} - {{ctrl.issue.issue_date}}</h2>
<div class="row">
<div class="col-sm-6">
<hh-field-messages>
<label for="issue_date">Issue Date</label>
<hh-american-date-field
id="issue_date"
name="issue_date"
ng-model="modelFormCtrl.model.issue_date"
ng-blur="modelFormCtrl.pageController.setStatus(this)"
ng-disabled="modelFormCtrl.pageController.readOnly"
same-or-earlier-than="{{ctrl.issue.issue_date}}"
same-or-earlier-than-msg="Enter a date that is on or before Resolution Date."
>
</hh-american-date-field>
</hh-field-messages>
<div class="hh-breath"></div>
</div>
</div>
</hh-model-form>
</div>
</div>
and here below is my angularjs file:
angular.module('Prm')
.controller('IssueDetailController',
['$scope', '$q', '$route', '$location', '$routeParams', 'moment', 'IssueService', 'IssuePriorityService', 'ActivityService',
'ProviderService', 'DirtyFormCheckingService', 'ConfirmBox', 'ErrorAlertService', 'AlertBoxService', 'DateService',
'ReferenceTableDataAdapter',
function ($scope, $q, $route, $location, $routeParams, moment, IssueService, IssuePriorityService, ActivityService, ProviderService,
DirtyFormCheckingService, ConfirmBox, ErrorAlertService, AlertBoxService, DateService,
ReferenceTableDataAdapter){
'use strict';
var ctrl = this,
isExisting = false,
issuePriority = null,
initPromises = [];
var currentUser = cpm.authentication.user.report_ownership_role_code;
ctrl.isAdmin = cpm.authentication.user.dss_role_list.split(",").includes('USERADMIN');
ctrl.readOnly = true;
var getNameForEdit = function(row) {
if (ctrl.readOnly) return 'View';
return 'Edit';
};
ctrl.providerAdapter = ReferenceTableDataAdapter('provider');
ctrl.ownerRoleAdapter = ReferenceTableDataAdapter('dss_report_owner_contact');
ctrl.providerIssueStatusAdapter = ReferenceTableDataAdapter('provider_issue_status');
ctrl.providerIssueSiteAdapter = ReferenceTableDataAdapter('provider_issue_site');
ctrl.providerIssuePriorityAdapter = ReferenceTableDataAdapter('provider_issue_priority');
ctrl.providerIssueCategoryAdapter = ReferenceTableDataAdapter('provider_issue_category');
if($routeParams.issue_code) {
isExisting = true;
initPromises.push(IssueService.get({id: $routeParams.issue_code}).$promise.then(function (data) {
ctrl.issue = data;
// placing this on the controller for the Parent Issue grid (if exists). Grid needs list of objects...
ctrl.parentActivities = [{'parent_provider_activity':ctrl.issue.parent_provider_activity,
'parent_provider_activity_activity_date':ctrl.issue.parent_provider_activity_activity_date,
'parent_provider_activity_description': ctrl.issue.parent_provider_activity_description}];
}));
} else {
ctrl.issue = IssueService.wrapData({
description: '',
resolution: '',
status: 'N',
site: '',
priority: 'N',
category: '',
provider: $routeParams.provider_code,
issue_date: new Date(),
owner_role: currentUser
});
ctrl.hide_resolution = true;
//ctrl.issue_date = new Date();
/* An issue may be created from a provider */
if($routeParams.provider_code) {
initPromises.push(ProviderService.get({id: $routeParams.provider_code}).$promise.then(function (data) {
ctrl.issue.provider = data.provider_code;
}));
}
}
/* Issues can have their due dates set based on their priority */
initPromises.push(IssuePriorityService.getPrioritiesMap().then(function (priorities) {
issuePriority = priorities;
if(!isExisting) {
ctrl.issue.due_date = moment(DateService.todayAsUtcDate()).add(issuePriority.N, 'day').toDate();
}
}));
/* Initialization */
$q.all(initPromises).then(function () {
/* Allow editing existing record only by owner & admins */
if(!isExisting || ctrl.isAdmin || ctrl.issue.owner_role === cpm.authentication.user.report_ownership_role_code) {
ctrl.readOnly = false;
}
// TODO: when grid actions are added
// ctrl.activitiesGrid.hideAddButton = ctrl.readOnly;
DirtyFormCheckingService($scope, 'issueForm', ctrl.issue);
});
ctrl.setDueDate = function (newModel, newCode) {
ctrl.issue.due_date = moment(ctrl.issue.issue_date).add(issuePriority[newCode], 'day').toDate();
};
ctrl.setResolutionDate = function (newModel, newCode) {
// ctrl.hide_resolution = (newCode !== 'R');
if (newCode == 'R') {
ctrl.issue.resolution_date = DateService.todayAsUtcDate();
} else {
ctrl.issue.resolution_date = null;
}
};
$scope.$watch('ctrl.issue.status', function (newCode) {
if(ctrl.issue) {
ctrl.hide_resolution = (newCode !== 'R');
}
});
ctrl.setStatus = function (event){
if (ctrl.issue.resolution_date) {
ctrl.issue.status = "R";
} else {
ctrl.issue.status = "N";
}
};
ctrl.submitSuccess = function() {
$location.url('/');
};
ctrl.parentActivityConfig = {
modelSetName: 'parentIssues',
actions: {
editRow: {
label: function(row) {
return ctrl.readOnly ? 'View' : 'Edit';
},
active: true,
callback: function(row){
$location.path('/activity/'+ctrl.issue.parent_provider_activity);
}
},
deleteRow: {
active: false
}
},
rowActions: ['editRow'],
columns: [
{col_description: 'Activity Date',
datatype: 'date',
model_field: 'parent_provider_activity_activity_date',
field_type: 'american_date',
field_name: 'activityDate'
},
{col_description: 'Description',
datatype: 'text',
model_field: 'parent_provider_activity_description',
field_type: 'text',
field_name: 'description'
},
]
};
ctrl.activitiesTableConfig = {
modelSetName: "activities",
serializerChildName: 'activities',
actions: {
addRow: {
label: 'Add Activity',
callback: function(){
$location.path('/provider/'+ctrl.issue.provider+'/add_activity/'+ctrl.issue.provider_issue_code);
},
active: function(row) {return !ctrl.readOnly;}
},
editRow: {
label: function(row) {
return getNameForEdit(row.modelSet);
},
active: true,
callback: function(row){
$location.path('/activity/'+row.modelSet.provider_activity_code);
}
},
deleteRow: {
active: function(row) {return !ctrl.readOnly;},
callback: function(row){
_.pull(ctrl.issue.activities, row.modelSet);
}
}
},
rowActions: ['editRow', 'deleteRow'],
columns: [
{col_description: 'Date',
datatype: 'date',
model_field: 'activity_date',
field_type: 'american-date',
field_name: 'activity_date'
},
{col_description: 'Type',
datatype: 'text',
model_field: 'provider_activity_type_description',
field_type: 'text',
field_name: 'provider_activity_type_description'
},
{col_description: 'Notes',
datatype: 'text',
model_field: 'description',
field_type: 'text',
field_name: 'description'
},
{col_description: 'Owner',
datatype: 'text',
model_field: 'owner_comp_name',
field_type: 'text',
field_name: 'owner_comp_name'
},
]
};
}]);
I'm trying my best to understand your question, but there's a lot of code to look through here. I do understand that you're trying to pass the current date to a function named "same-or-earlier than." However I can't seem to find a function with that name in your controller file.
I'm assuming that you've got a custom directive (attribute directive) that accepts the current date.
Either way, a simple solution for your problem of passing the current date could be to write a small function that when invoked returns the date using Javascript's native "Date" object.
Perhaps like this in your controller:
ctrl.returnCurDate = function() {
return new Date();
};
That way in your markup, you can invoke the method we've defined since it's attached to the scope of your controller.
same-or-earlier-than = "ctrl.returnCurDate()"
I hope I'm answering your problem in a relevant fashion, please feel free to ask further if I've misunderstood your question.
Best of luck.
P.S. Inherently there are some pain-in-the-butt formatting issues that come with using JS's native Date constructor, I would consider using a library such as "Moment.js" to relieve you of parsing the returned value when invoking:
new Date();

Subscribing the collection (Meteor)

I have some specific problem.
I use MeteorJS and installed yogiben:admin. I tried to build some schema, but I have an error after updating something.
I want to add that I have subpages in page, maybe that's the problem?
That's what I get after adding items to my invoice:
http://s7.postimg.org/l0q52l27v/error.png
As I can see in the picture, the problem is with some modifier and with "After.Update.sum". I use function that use "sum".
In my "server/collections/invoices_item.js"
I have:
InvoicesItem.after.update(function(userId, doc, fieldNames, modifier, options) {
var sum = 0; InvoicesItem.find({ invoiceId: doc.invoiceId }).map(function(item) { sum += item.amount; }); Invoices.update({ _id: doc.invoiceId }, { $set: { totalAmount: sum }});
});
Than I saw that problem could be with "totalAmount:sum". I use Chrome, so I tried "console.log()" to see if the page takes my collection.
And it doesn't.
I use Chrome, so I tried to see what the console will give me. I have something like this: http://s4.postimg.org/rusm4wx9p/fakturka.png
I did sth like that in my code on server side:
Meteor.publish("fakturka", function(invoiceId) {
return Invoices.find({_id:invoiceId,ownerId:this.userId}, {});
});
And did that on client side:
this.InvoicesNewInsertController = RouteController.extend({
template: "InvoicesNew",
yieldTemplates: {
'InvoicesNewInsert': { to: 'InvoicesNewSubcontent'}
},
onBeforeAction: function() {
/*BEFORE_FUNCTION*/
this.next();
},
action: function() {
if(this.isReady()) { this.render(); } else { this.render("InvoicesNew"); this.render("loading", { to: "InvoicesNewSubcontent" });}
/*ACTION_FUNCTION*/
},
isReady: function() {
var subs = [
Meteor.subscribe("invoices_item"),
Meteor.subscribe("invoiceeeee"),
Meteor.subscribe("customers"),
Meteor.subscribe("fakturka", this.params.invoiceId),
Meteor.subscribe("invoices_item_empty_faktura"),
Meteor.subscribe("invoices_itemss_faktura", this.params.invoiceId)
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {},
invoices_item: InvoicesItem.find({}, {}),
invoiceeeee: Invoices.find({}, {}),
customers: Customers.find({}, {}),
fakturka: Invoices.findOne({_id:this.params.invoiceId}, {}),
invoices_item_empty_faktura: InvoicesItem.findOne({_id:null}, {}),
invoices_itemss_faktura: InvoicesItem.find({invoiceId:this.params.invoiceId}, {})
};
/*DATA_FUNCTION*/
},
onAfterAction: function() {
}
});
I'm sorry for so much code, but I really want to solve that problem and I want to give so much info as I could. Please, help me to solve my problem.
After removing that code from: both/collections/invoices.js
Schemas={};
Schemas.Invoicess = new SimpleSchema({
invoiceNumber:{
type:Number
},
date_issued:{
type:Date
},
date_due:{
type:Date
},
customerId:{
type:String
},
totalAmount:{
type:String
}
});
Invoices.attachSchema(Schemas.Invoicess);
"fakturka" is visible. After adding that code - "fakturka" in undefined.

Data deleted from DB successfully but not refreshed the current page in AngularJS

I tried several times to delete data and it successfully delete data but not show updated the student full list.....
After manually refresh the web page then it shows the updated student list please help me.
X.controller('StudentController', ['$scope', 'Student', 'Department', '$routeParams','$location', function ($scope, Student, Department, $routeParams,$location) {
$scope.v = 'test value';
$scope.profileid = $routeParams.Id;
console.log($scope.profileid);
////////////////RETRIVE ALL DATA FROM DB///////////////
function init() {
/////RETRIVE DATA FOR STUDENT/////////
$scope.student = { Name: '', Phone: '', Class_id: '', Department_id: '' };
$scope.students = [];
Student.get(function (response) {
console.log("List of Student");
$scope.students = response.Data;
console.log($scope.students);
});
///////RETRIVE DATA FOR DEPARTMENT////////////////////
$scope.depts = [];
Department.get(function (response) {
console.log("List of Dept");
$scope.depts = response.DeptData;
console.log($scope.depts);
});
};
////////////RETRIVE SPECIFIC DATA INTO DB/////////////
Student.get({ Id: $scope.profileid }, function (response) {
console.log("SPECIFIC DATA");
$scope.student = response.Data;
console.log($scope.students);
});
/////////////////////////////DELETE//////////////////
$scope.Stddelete = function (profileId) {
Student.delete({ Id: profileId });
console.log("DELETE");
init();
};
init();
}
]);
To update the DOM, you need to splice the object from the array.
$scope.students.splice($index,1);
Example:
$scope.Stddelete = function (profileId,index) {
Student.delete({ Id: profileId });
$scope.students.splice(index,1);
console.log("DELETE");
init();
};

Returning data from service dependancy using promises causes $digest iteration error

I have two services where one needs to query the other by an id for example.
This is what I currently have but I'm getting $digest iteration limits.
"Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
Controller
angular.module('exampleApp')
.controller('ExampleCtrl', function ($scope, PeopleService, PlanService) {
$scope.plan = new Plan();
// or
$scope.plan = Plan.get({ id: 1 });
// Used to populate a <select> menu in the view
PeopleService.all().then(function(data) {
$scope.people = data;
});
});
PlanService
angular.module('exampleApp')
.factory('PlanService', function($resource, PeopleService){
// Resource example
// { id: 1, title: 'Example', assignee_id: 1 }
var Plan = $resource('/plans/:id', { id: '#id' }, {
'query': { method:'GET', isArray: true },
'get': { method:'GET', isArray: false },
'update': { method:'PUT' }
});
// Return the matching person from PeopleService
Plan.prototype.assignee = function() {
if(this.assignee_id) {
return PeopleService.find_by_id(this.assignee_id)
} else {
return null;
}
}
return Plan;
});
PeopleService
angular.module('exampleApp')
.service('PeopleService', function($http, $q){
var people_array = $q.defer();
// This list is reasonably static hence why I feel no need to make it it's own resource
// Contains an array of people objects for example
// { id: 1, name: 'Paul Smith', hourly_rate: 5.0, max_hours: 8 }
$http.get('/people/json').then(function(result) {
people_array.resolve(result.data);
});
this.all = function() {
return people_array.promise;
};
this.find_by_id = function(id) {
var def = $q.defer();
people_array.promise.then(function(data) {
// underscore.js find
var person = _.find(data, function(person) {
return parseInt(person.id) === parseInt(id);
})
def.resolve(person);
});
return def.promise;
};
});
View
<select name="person_id" class="form-control" ng-model="plan.assignee_id" ng-options="assignee.id as assignee.name for person in people" required>
</select>
{{ plan.assignee().name }}
Now the select populates no problem, however the plan.assignee.name causes the digest errors when using the select menu to select an option. I'm sure this is a misunderstanding I have with how promises work so I'd appreciate a nudge in the right direction.

Angular Service throws exception when returning a promise

In my app.js code I'm running some init code which pulls session vars from the server.
Good so far; however I'm now trying to add an additional call to pull data for a treeview widget. This new call is causing the JavaScript exception :
"Cannot read property 'then' of undefined"
The startup code is:
1) app.run gets called first,
2) call into 'userService' to init various $rootScope vars
3) userService makes API calls to a server and returns data. $q.defer() and $http is used
** NEXT STEPS CAUSES AN EXCEPTION
4) call into userService.getUserReportsTreeFromDataContext() from app.run
5) userService.getUserReportsTreeFromDataContext then calls down into datacontext.js (THIS SOMEHOW CAUSES AN EXCEPTION).
Here is my app.run() code within app.so
app.run(['$route', '$rootScope', 'common', 'userService', function ($route, $rootScope, common, userService) {
// initialize session vars
userService.openUserSession(razorEnvJson).then(function (data) {
var sessionID = data.data[0];
$rootScope.rageSessionVars.sessionID = sessionID;
// **** THROWS EXCEPTION HERE ****
userService.getUserReportsTreeFromDataContext().then(function (data){
// var myData = data;
});
});
}]);
and a snippet from userContext.js service :
this.openUserSession = function (razorEnvParams) {
_razorEnvParams = razorEnvParams;
_// some vars ommitted here for brevity
var url = "http://" + _domain + ":" + _port + controllerpath + "?userid=" + user + "&pass=" + pass;
var deferred = $q.defer();
deferred.notify("Opening user session...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true',
'Content-Type': 'application/json'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
}).error(function (data, status, headers, config) {
log("Cannot open a user session via api call. Errors details: " + data);
});
return deferred.promise;
}
this.getUserReportsTreeFromDataContext = function (userID) {
datacontext.getReportsTree().then(function (data) {
return data;
});
}
and my datacontext.js code to pull data from server, or to pull some test data :
(function () {
'use strict';
var serviceId = 'datacontext';
angular.module('app').factory(serviceId, ['$http', '$rootScope', 'common', datacontext]);
function datacontext($http, $rootScope, common) {
var $q = common.$q;
var service = {
getReportsTree: getReportsTree,
sendAggrRequestToServer: sendAggrRequestToServer,
};
return service;
function getReportsTree() {
var reportsJson = [
{
id: 1, text: "Standard", expanded: false, spriteCssClass: "rootfolder", checkChildren: true, items: [
{ id: 3, text: "MTM Aggr", reptName: "MTM Aggr" },
{ id: 4, text: "Member Aggr", reptName: "Member Aggr" }
]
},
{
id: 30, text: "Hierarchy", expanded: false, spriteCssClass: "rootfolder", checkChildren: true, items: [
{ id: 31, text: "Ctpy Hrchy", reptName: "CTPYHIER", withHierarchy: 'true' },
{ id: 32, text: "Ctpy/BkgLocation Hrchy", reptName: "CTPYHIER_BKG_LOC", withHierarchy: 'true' }
]
}
];
return $q.when(reportsJson);
}
})(); // end datacontext.js
FYI - I make many other successful calls from my dashboard.js controller into datacontext.js with no problems.
Here's a good example, where some test data is pulled from datacontext :
dashboard.js -
function getPositionsData() {
datacontext.getPositions().then(function (data) {
vm.positionsData = data;
populateGridDataSource(vm.positionsData);
});
}
datacontext.js -
function getPositions() {
var positionsJson = [
{ id: 1, product: "BAX", instrument: "BOND-0003", position: 11, delta: 0.02, gamma: 0.79, initMarin: 600, initMarginPctChange: 250, varMargin: 75 },
{ id: 2, product: "BAX", instrument: "BOND-0004", position: -4, delta: 0.12, gamma: 0.46, initMarin: 400, initMarginPctChange: 300, varMargin: 65 },
{ id: 3, product: "BAX", instrument: "BOND-0004", position: 9, delta: 0.09, gamma: 0.55, initMarin: 700, initMarginPctChange: 200, varMargin: 40 }
];
return $q.when(positionsJson);
}
you forgot to return your initial promise in the getUserReportsTreeFromDataContext function: should be like this:
this.getUserReportsTreeFromDataContext = function (userID)
{ return datacontext.getReportsTree()
.then(function (data) { return data; });
}

Categories

Resources