Using $http.get in ng-repeat causes multiple errors - javascript

I have a function what returns an array of items by group Id. Here it is:
var getChoices = function (groupId) {
var request = $http.get(_baseUrl + 'choice', { params: { choiceGroupId: groupId } });
return request.then(function(result) {
if (resources.ok(result)) {
return result.data.items;
}
}, function(error) {
});
}
It works fine when I bind it to button, but when I try to make ng-repeat over this function results I have multiple errors in browser console.
<md-list>
<md-list-item ng-repeat="choice in getChoices(choiceGroupId)">
{{choice}}
</md-list-item>
</md-list>
I've also tries this, but result is the same.
<md-list ng-init="choices = {{getChoices(choiceGroupId)}}">
<md-list-item ng-repeat="choice in choices">
{{choice}}
</md-list-item>
</md-list>
I've seen answers to questions like this, but there people suggested to make request in the controller, then fill the array with data, and iterate over array values, but this doesn't suit my case because I need that choiceGroupId from the UI side.
It seems like browser tries to evaluate get request on each tick and something like overflow happens. How can I handle this to call 'get' once and then iterate over returned result?

Check If your choices variable has duplication of value , If yes than try below code
<md-list>
<md-list-item ng-repeat="choice in choices track by $index">
{{choice}}
</md-list-item>
</md-list>
var getChoices = function (groupId) {
var request = $http.get(_baseUrl + 'choice', { params: { choiceGroupId: groupId } });
return request.then(function(result) {
if (resources.ok(result)) {
$scope.choices= result.data.items;
}
}, function(error) {
});
}

Related

how to return database result through angular method

I want to know if its possible to return database result through angular method call within an ngRepeat template. To clarify here is my template:
<div class="article-right" ng-repeat="localNews in allLocalNews | limitTo:5">
<div class="article-title">
<p>
On {{localNews.dte | date}}
<a>Number of comment: {{getNumberOfComment(localNews.id)}} </a>
</p>
</div>
and here is my controller, Within my controller I have a method which accepts each id value of results in ngRepeat to fetch the number of comments from the database
$scope.getNumberOfComment = function(id){
var cObj = {id:id}; //get a news number of comments
return $http.post("shared/search/getNumberOfComment.cln.php",cObj).success(function(response){
if(response != "failed"){
return response;
}
}).error(function (response, status) {
console.log(response);
});
}
This scripts makes my browser to freeze as it goes into loop. Any help will be highly appreciated.
It probably loops because each digest cycle it will remake the calls to get the info.
You better off having a variable that gets populated per item and calling something like ng-init on each element which will only get called once to initialise you item variable.
Does that make sense?
eg
<div class="article-right" ng-repeat="localNews in allLocalNews | limitTo:5">
<div class="article-title">
<p>
On {{localNews.dte | date}}
<a ng-init=getNumberOfComment(localNews.id, localNews)>Number of comment: {{localNews.myVar}} </a>
</p>
</div>
$scope.getNumberOfComment = function(id, localNews){
var cObj = {id:id}; //get a news number of comments
return $http.post("shared/search/getNumberOfComment.cln.php",cObj).success(function(response){
if(response === "passed"){
localNews.myVar = response;
}
}).error(function (response, status) {
console.log(response);
});
}
The solution is simple, use get call on controller init to get all comments data. Then using ng-repeat iterate on this collection and show only those data you want for a proper news id. If you want only a number of comments, here is the example, it is not tested but you should get the idea. It requires from you to prepare API endpoint to return all the comments.
function CommentsController() {
var vm = this;
vm.comments = [];
getComments();
function getComments() {
$http.get("your/api/getComments.cln.php").success(function(r){
vm.comments = r;
}
}
function getNumberOfComment(newsId) {
return vm.comments.filter(function(comment){
return comment.news_id === newsId;
}).length;
}
}
<div class="article-right" ng-repeat="localNews in allLocalNews | limitTo:5">
<div class="article-title">
<p>
On {{localNews.dte | date}}
<a>Number of comment: {{$ctrl.getNumberOfComment(localNews.id)}} </a>
</p>
</div>

Angular - Assign new value to FirebaseListObservable

Not sure how this is suppose to be done.
filter is a Firebase list observable.
filter: FirebaseListObservable<UserModel[]>;
This is the query. It gets all users with a specific occupation.
this.filter = this.db.list('occupationsUsers/' + occupation + '/users');
Then I use an <md-list> which works. It displays all users with occupation.
<md-list>
<md-list-item *ngFor="let user of filter | async" [value]="user.email">{{user.email}}
<button md-button [mdMenuTriggerFor]="menu">Menu</button>
<md-menu #menu="mdMenu">
<button md-menu-item (click)="removeUserFromFilterList(user.email)">Delete</button>
</md-menu>
</md-list-item>
</md-list>
removeUserFromFilterList
removeUserFromFilterList(userEmail: string) {
var index = this.eventForm['guests'].indexOf(userEmail);
this.filter = this.eventForm['guests'].splice(index, 1);
}
The error:
ERROR Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'
at invalidPipeArgumentError
How do I populate this.filter with the new updated user list and keep it working with the firebase query?
this.filter as you mention , is a FirebaseListObservable. and as i understand , this.eventForm is just an array(and not like this.filter).
i would recommend you to use one of the following methods:
this.filter.update('key-of-some-data', { object to remove });
or
this.filter.remove('key-of-some-data');
you can read more about that on
click here

Storing strings in array as user selects checkbox

I just started using angularJS and am trying to learn how to insert strings in array when user clicks checkbox and later access these values.
This is what I have so far:
<md-button class="toolbar-button" ng-click="removePlan()">
<md-icon>delete</md-icon>
</md-button>
<md-list-item ng-repeat="plan in plans">
<md-checkbox ng-model="plansSelected[plan._id]"> </md-checkbox>
</md-list-item>
apps.js
$scope.plansSelected = []
$scope.removePlan = function () {
for (var plan in $scope.plansSelected) {
if ($scope.plansSelected[plan] === true) {
projectResource.removePlan(plan).then(function (data) {
if (data.success) {
$scope.plans.push(data.plan)
}
})
}
}
}
projectResource.js
resource.removePlan = function (planId) {
return $http.delete(getPlanUrl(planId)).then(processResponse, processError)
}
function getPlansUrl () {
return getProjectUrl() + '/plans'
}
function getPlanUrl () {
return getPlansUrl() + '/' + $route.current.params.planId
}
In debugger this is how my array looks like:
$scope.plansSelected: Array[0]
57bd40128a58022800887d80:false
57bd40328a58022800887d88:false
57cc2bcbb452140500b0334a:false
I am checking if user removed selection from the checkbox and if the value is true then take that plan._id and pass in the loop to removePlan function.
Does anyone see what I am doing wrong, because this is not working.
Please be more specific what "this is not working" means - it's hard for us to detect that without being able to run it.
I can see that your use of $scope.plansSelected as an empty array is wrong. I would dispense with that and do it like this:
<md-list-item ng-repeat="plan in plans track by $index">
{{plan.name}} <md-checkbox ng-model="plans[$index].selected"> </md-checkbox>
</md-list-item>
This basically adds a 'selected' attribute to your plans array, and make it easier for you to iterate over the plans array and pull out the ones you want.

How to programmatically select ng-option value?

I have a view that is filled with dropdownlists to filter a report. I also have a view of saved filters that are displayed as links. When a user clicks on their saved filters, I want the appropriate values of the dropdownlists to be selected. The drop downs are being populated properly. On the saved filter link there is an ng-click that will call a function that iterates through the collection of saved filter values and automatically selects the correct one. I cannot figure out how to programmatically set the selected option. Any help is much appreciated!
<select uid="locSelect"
class="span12"
ng-model="reportDetail.selectedLoc"
ng-options="loc.dbid as loc.serviceName for loc in reportDetail.locList | orderBy:'name'">
<option uid="unselectedLocOption" value="">-- Select One --</option>
</select>
Here is the list of saved filters:
<div class=" well fixed-search" style="overflow-x: hidden;overflow-y: auto;">
<div class="well-header">
Saved Filters
</div>
<div ng-if="!hasSavedFilters">
<span>No saved filters</span>
</div>
<ul ng-if="hasSavedFilters" class="nav nav-list dashboard-list">
<li ng-repeat="filter in reportDetail.savedFilters">
<a uid="savedFilter" href="" ng-click="reportDetail.loadSavedFilters(filter.filters)">
<span ng-bind="filter.title"></span>
</a>
</li>
</ul>
And here is my controller
(function(){
'use strict';
var ReportDetailController = function(ReportsService, $scope){
var _locList = {};
var _hospitalStatusList = {};
var _providerStatusList = {};
var _savedFilters = [];
var _sourceTypeList = {};
var _dateRangeList = {};
var _init = function(){
ReportsService.getCurrentReportSavedFilters().then(function(data){
$scope.reportDetail.savedFilters =data;
$scope.hasSavedFilters = ReportsService.hasSavedFilters();
});
ReportsService.getLOCListForDDL().then(function(data){
$scope.reportDetail.locList = data;
//$scope.reportDetail.selectedLoc = $scope.reportDetail.locList[0];
});
ReportsService.getSelectListData()
.then(function(data){
$scope.reportDetail.sourceTypeList = data.CONNECTION_TARGET_STATUS;
$scope.reportDetail.hospitalStatusList = data.CONNECTION_SOURCE_STATUS;
});
ReportsService.getDateRangesForDDL()
.then(function(data){
$scope.reportDetail.dateRangeList = data;
});
$scope.reportDetail.providerStatusList = ReportsService.getProviderStatusForDDL();
};
var _loadSavedFilters = function(filters){
for(var i = 0, l = $scope.reportDetail.locList.length; i<l; i++){
if($scope.reportDetail.locList[i].serviceName == filters.levelOfCare){
$scope.reportDetail.selectedLoc = $scope.reportDetail.locList[i];
console.log($scope.reportDetail.selectedLoc);
}
}
}
var _isActive = function(filter){
for(var i = 0, l = $scope.reportDetail.savedFilters.length; i<l; i++){
if(filter.title == $scope.reportDetail.savedFilters[i].title){
return true;
}
return false;
}
}
var _generateReport = function(){
return ReportsService.generateReport();
};
$scope.reportDetail = {
init: _init,
selectedLoc: null,
isActive: _isActive,
locList: _locList,
selectedHospitalStatus: 'NOTIFIED',
hospitalStatusList: _hospitalStatusList,
selectedProviderStatus: 'NEW',
providerStatusList: _providerStatusList,
selectedSourceType: 'CONNECTED',
sourceTypeList: _sourceTypeList,
selectedDateRange: '',
dateRangeList: _dateRangeList,
savedFilters: _savedFilters,
loadSavedFilters: _loadSavedFilters,
generateReport: _generateReport
};
$scope.reportDetail.init();
};
app.controller('ReportDetailController', ['ReportsService', '$scope', ReportDetailController]);
})();
You just need to set the ng-model to whatever it should be, so in this case you would set reportDetail.selectedLoc to whatever loc.dbid it should be.
For example: http://jsfiddle.net/uWLua/1/
Note: Make sure they have the same type, so in your example make sure they are either both integers, or both strings, it will not know they are the same if you have one as 5073 and one as "5073"
I updated the fiddle to show that the string and number do not do the same thing.
The ng-model and the expression feeding ng-options -must- match in order for Angular to compare values and see what option is 'selected'. Just as 'dave' indicated.
Due to time constraints I ended up going a different route. I created an event bus of sorts in my service layer and subscribe to the even in my controller, updating the model, and used ng-repeat with ng-selected.
I'm still interested to understand why this was not working with ng-options. The model and ng-options types matched, and everything appeared to be wired up correctly. When I have more time i'll re-address the original issue. Thanks for all who responded!
You need custom directive, or something similar to this two approaches
<div ng-controller="MyCtrl">
<h1>Approach 1</h1>
<span ng-repeat="val in dbs">
<input type="checkbox" ng-model="val.checked">{{val.name}}
</span>
<hr/>
<h1>Approach 1</h1>
<select multiple>
<option ng-repeat="val in dbs" name="val.name" value="val.name" ng-selected="val.checked">{{val.name}}</option>
</select>
<h4>Source (note scope changes)</h4>
{{dbs}}
</div>
also you can use ng-change to do some complex ops
If I understand, in summary, you have a select filled with a list, and you want to programmatically set one of those to be selected, type it as the default right?
If so, you can easily solve this with ng-options, just associate your controller instance with scope and assign the position of the list you want to the model of select, for example:
Select HTML
<select ng-model="vm.aluno_id" name="aluno_id" ng-options="aluno.nome for aluno in alunos">
Controller
app.controller("auxiliarController", function( $scope){
//instancia controller;(Controller instance;)
var vm = this;
$scope.vm = vm;
//carregando lista no scope, que serĂ¡ utilizado pelo angular no select
//Loading list in scope, which will be used by angular in select
$scope.alunos = [{id: 1, nome: "aa"}, {id: 2, nome: "bb"}];
//setando item default no select
$scope.vm.aluno_id = $scope.alunos[0];
});
I hope I have helped

Angular filtering doesn't work

In my template I have this code:
<li class="row timeline-item" data-ng-repeat="item in data | filter:workoutFilter" data-ng-include="getTemplateUrl(item)"></li>
And in my controller I have:
$scope.workoutFilter = null;
$rootScope.$on('workout', function(e, data) {
$scope.workoutFilter = "{Type: 'workout'}";
});
When I click button workouts, everything just disappears as if there are no items that match this filter, but that isn't the case (and I know this for a fact because getTemplateUrl detects type workout and returns right template)
Why is this happening ? Is there any other way I can filter items which have property Type "workout" ?
EDIT
Here is what happens when I click button:
In my other controller :
$scope.onWorkoutsClick = function () {
feedService.setWorkoutFilter();
};
In service:
setWorkoutFilter : function() {
$rootScope.$broadcast('workout');
}
And in my main controller:
$rootScope.$on('workout', function(e, data) {
$scope.workoutFilter = "{Type: 'workout'}";
});
I assume you're trying to filter based on item.Type == 'workout'?
You need to set your filter to an object rather than a string:
$scope.workoutFilter = {Type: 'workout'};

Categories