Output is concatenated - angularjs

New click on [Filter] does not clear previous output but adding to exists.
For example, if filtered by "banned" I see the banned users list, next filter by "registered" does not remove the "banned" but adding the "registered" to the end of the table.
In controller $scope.site_users overwritten, but somewhere it still saves the previous filter output.
Why is that happens? May be something on packages side?
Installed packages:
urigo:angular - Angular
angularui:angular-ui-router
accounts-password
accounts-ui
twbs:bootstrap
Removed packages:
insecure
autopublish
Or in code
Controller:
angular.module("sis_admin_am").controller("UsersListCtrl", ['$scope', '$meteor',
function($scope, $meteor){
$scope.filter = function(){
$scope.site_users = '';
$scope.site_users = $meteor.collection(Users).subscribe('site_users_filtered', {status: $scope.userStatus});
};
}
]);
View:
<form ng-submit="filter()">
<button>Filter</button>
<select ng-model="userStatus" >
<option ng-selected="selected">banned</option>
<option>registered</option>
<option>active</option>
</select>
</form>
<p></p>
<table class="table">
<tr class="panel panel-default">
<th>Name</th>
<th>Email</th>
</tr>
<tr ng-repeat="user in site_users">
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
</tr>
</table>
Server part:
Meteor.publish('site_users_filtered', function(options) {
console.log('options:', options);
return Users.find(options);
});

That's because how Subscriptions in Meteor works.
If you add or change a subscription without closing the ones before, it will just add them all together (which is good but you have to be aware of it).
If you want to filter with subscriptions (for security reasons) you should change your code like that:
angular.module("sis_admin_am").controller("UsersListCtrl", ['$scope', '$meteor',
function($scope, $meteor){
var savedSubscriptionHandle = null;
$scope.filter = function(){
savedSubscriptionHandle.stop();
$scope.site_users = '';
$scope.site_users = $meteor.collection(Users);
$scope.$meteorSubscribe('site_users_filtered', {status: $scope.userStatus}).then(function(handle){
savedSubscriptionHandle = handle;
});
};
}
]);
But if you don't mind keeping all the data in the local cache it might be easier to use Angular's filters or Meteor's cursor syntax to filter the display.
More detailed explanation here:
http://angular-meteor.com/tutorial/step_12

I think your problem is, ngSelected NOT necessarly select only one choice of your dropdown.
and that is because,tchnically you should de-select your unwanted userStatus manually as they do in the official doc :
https://docs.angularjs.org/api/ng/directive/ngSelected
You can try to send your ng-model (userState) along to the filter() function and actually filter with that value directly without having to check the scope.

Related

How get my controller to make GET request when tab is selected?

I am pretty new to angular and I am working on a data entry web page. The web page has three tabs. Vendor, Products and Types. I started working on the Types tab first. I'd be happy if I could just display the results of a GET request to my Rest API. My Rest API works:
# curl http://192.168.1.115:8080/type
[
{"_id":"56415e7703aba26400fcdb67","type":"Skiing","__v":0},
{"_id":"56417a8503aba26400fcdb68","type":"Bannana","__v":0},
{"_id":"56417a8d03aba26400fcdb69","type":"Carrot","__v":0},
{"_id":"56417a9603aba26400fcdb6a","type":"Beer","__v":0}
]
Here's the pertinent part of my html UPDATED I now have st-safe-src=all_typesbut still no joy ...
<div ng-controller="typeCtrl" class="tab-pane" id="types-v">
<p>The number {{3 + 4}}.</p>
<p>message is {{message}}</p>
<table st-table="displayedCollection" st-safe-src="all_types" class="table table-striped">
<tbody>
<tr ng-repeat="x in displayedCollection">
<td>{{x.type}}</td>
</tr>
</tbody>
</table>
</div> <!-- end Types Tab -->
... and here is my typeCtrl.js ...
app.controller("typeCtrl", function($scope,$http) {
$scope.type_to_look_for = "";
$scope.message = "this is the message. (from typeCtrl)";
$scope.itemsByPage=15;
$scope.all_types = function () {
$http.get("http://192.168.1.115:8080/type").then(function(response) {
console.log(response);
console.log(response.data);
return response.data;
});
}
});
... but when I click on the Types tab my data does not display. I looked developer console and I do not even see the GET request kickoff. And my web page looks like this ...
... what am I doing wrong?
There is nothing that calls all_types. Run http.get and assign the response to all_types
app.controller("typeCtrl", function($scope,$http) {
$scope.type_to_look_for = "";
$scope.message = "this is the message. (from typeCtrl)";
$scope.itemsByPage=15;
$http.get("http://192.168.1.115:8080/type").then(function(response) {
$scope.all_types = response;
});
}
});
My understanding is that you want a get request to be fired whenever you click on the Types tab, right? If so, just use ng-click to call your all_types function as follows:
<div ng-controller="typeCtrl" ng-click="all_types()" class="tab-pane" id="types-v" >
Also, you do not need to return response.data in your controller. Just assign the data to a scope object and use it in the template.
And finally, I would suggest wrapping all your ajax calls in factories and then inject those factories in your controllers.
Here is your code
<div ng-controller="typeCtrl" class="tab-pane" id="types-v">
<p>The number {{3 + 4}}.</p>
<p>message is {{message}}</p>
<table st-table="types" class="table table-striped"><!-- Do not need st-safe-src -->
<tbody>
<tr ng-repeat="x in types"><!-- Use the Collection name as types-->
<td>{{x.type}}</td>
</tr>
</tbody>
</table>
</div>
Controller Code
app.controller('typeCtrl', function($scope, $http) {
$scope.type_to_look_for = "";
$scope.message = "this is the message. (from typeCtrl)";
$scope.itemsByPage=15;
$http.get("http://192.168.1.115:8080/type").then(function(response) {
console.log(response.data);
$scope.types = response.data;
});
});
Here is working the plunker

angular edit details using REST($resource) Service

I have a table with result set and there is edit option existing in each row. After clicking on the 'edit' link, i am able to populating the content on the fields.
But how do i edit the existing content using REST Service.
<table class="table-bordered table">
<thead>
<tr>
<th>id</th>
<th>Director</th>
<th>genre</th>
<th>releaseYear</th>
<th>title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="result in results | orderBy:'_id'">
<td>{{result._id}}</td>
<td>{{result.director}}</td>
<td>{{result.genre}}</td>
<td>{{result.releaseYear}}</td>
<td>{{result.title}}</td>
<td>Edit | Delete</td>
</tr>
</tbody>
</table>
controller
$scope.saveContact = function(){
//save or edit contact
};
I have created in plunker.
content EDIT using REST API
I put it into work. You were close to the solution.
Here is the working plunker
What i did :
1 - I changed your way of getting the element for the form.
HTML
//I give the complete object instead of the id
ng-click="edit(result)"
Controller
//I prefer to pass the entire object
$scope.edit = function(result){
$scope.cineresultsFrm = angular.copy(result);
};
Service
I just removed the service. It wasn't useful anymore.
2 - I used the method of the ressource on your object
Controller
$scope.saveContact = function(){
//The function given to $update() is the .then() function
$scope.cineresultsFrm.$update(function(){
//If the update succeed i update the whole list. Could be done a better way but if you don't have any performance issues that will do the job.
$scope.getMovies();
});
};
I also changed the way you handle the "then" in the promise. But this is just a matter of taste.
$scope.getMovies = function(){
$scope.movieResults = movie.query(function() {
$scope.results = $scope.movieResults;
});
};
$scope.getMovies();
Hope it helped you

Angularjs state retension

I am adding row dynamically using angularjs. But the problem is that I want to retain this state all over the application. For example in view-1 I add one dynamic row to the table and move to view-2 after coming from view-2 the added row should be available. So is there any method to retain the state of view in angularjs. Following is the code I used to add row dynamically:
angular.module('MyApp', [])
.controller('MainController', [ '$scope', function($scope) {
$scope.rows = ['Row 1'];
$scope.counter = 2;
$scope.addRow = function() {
$scope.rows.push('Row ' + $scope.counter);
$scope.counter++;
}
}]);
<body ng-controller="MainController">
Add Row {{counter}}
<table>
<thead>
<tr>
<th width="200">Some Header</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rowContent in rows">
<td>{{rowContent}}</td>
</tr>
</tbody>
</table>
</body>
Thanks.
Yes. You should save the model used to build the table (with the new rows aswell) to a Service. Then you inject that service in your controllers.
To be able to see a little bit of your code would be nice, though. But here goes an example of how to do this:
DISCLAIMER
Untested example
angular.module('yourapp').factory('MySharedService',function(){
var myTableModel = [];
function addRow(row){
myTableModel.push(row);
return myTableModel;
}
return {
addRow: addRow,
tableModel: myTableModel
}
})
.controller('MyFirstController',['$scope','MySharedService',function($scope,
MySharedService){
$scope.tableModel = MySharedService.tableModel;
$scope.addRow = function(row){
$scope.tableModel = MySharedService.addRow(row);
}
}]).controller('MySecondController',['$scope','MySharedService',function($scope,
MySharedService){...}]);
EDIT:
After researching a bit further on this, I've found a similar question with a couple ways of achieving this and with sample code here
Check it out and see if it helps you.

ng-repeat ng-click when the click function has already been called earlier in the code

First off, I read the plethora of other questions and answers regarding ng-click, ng-repeat, and child and parent scopes (especially this excellent one.)
I think my problem is new.
I'm trying to call a function using ng-click within a table. The app allows for the sorting of Soundcloud likes. The problem is that when I try to call the ng click function using new data, it still tries to call the function using the old data. Let me explain better with the example:
Controller:
function TopListCtrl($scope, $http) {
$scope.sc_user = 'coolrivers';
$scope.getData = function(sc_user) {
var url = 'http://api.soundcloud.com/users/'+ $scope.sc_user +'/favorites.json?client_id=0553ef1b721e4783feda4f4fe6611d04&limit=200&linked_partitioning=1&callback=JSON_CALLBACK';
$http.jsonp(url).success(function(data) {
$scope.likes = data;
$scope.sortField = 'like.title';
$scope.reverse = true;
});
}
$scope.getData();
$scope.alertme = function(permalink) {
alert(permalink);
};
}
HTML
<div id="topelems">
<p id="nowsorting">Now sorting the Soundcloud likes of <input type=text ng-model="sc_user"><button class="btn-default" ng-click="getData(sc_user);">Sort</button></p>
<p id="search"><input ng-model="query" placeholder="Filter" type="text"/></p>
</div>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Song</th>
<th>Artist</th>
<th>Likes</th>
<th>Played</th>
<th>Tags</th>
</tr>
</thead>
<tr ng-repeat="like in likes.collection | filter:query | orderBy:sortField:reverse">
<td width="30%"><a href="{{ like.permalink_url }}">{{like.title}}</td>
(Trying to call it here) <td>{{like.user.username}}</td>
<td>{{like.favoritings_count}}</td>
<td>{{like.playback_count}}</td>
<td>{{like.tag_list}}</td>
</tr>
</table>
</div>
</body>
</html>
So I have that function getData. I use it to load the data in using the soundcloud api. I have a form at the top that uses getData to load a new user's Soundcloud data in. I also call the getData function in the controller so that there is an example on the page upon loading.
The problem is when I try to load a new user's data from a <td> I want to be able to click on the user to see and sort their likes.
How do I 'clear' the function or the global namespace (am I even refering to the right thing)? How can I reuse the getData function with a new variable?
Working Jsfiddle for this
In your getData function you have this line:
var url = 'http://api.soundcloud.com/users/'+ $scope.sc_user +'/favorites.json...
but you are passing in the variable sc_user to your getData function and should be using it like this (no $scope):
var url = 'http://api.soundcloud.com/users/'+ sc_user +'/favorites.json...
That being said... your initial data load fails because you are calling:
$scope.getData();
and not:
$scope.getData($scope.sc_user);

AngularJS calling a function inside a controller with ng-click

I've got a problem with getting my function inside my controller to work properly.
given the following partial:
<div ng-controller="KundeDetailCtrl"><table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>InstallationsID</th>
</tr>
</thead>
<tbody >
<tr data-ng-repeat="mandant in kunde.mandanten" ng-click="getMandant(mandant)" >
<td> {{mandant.name}}</td>
<td>{{mandant.id}}</td>
</tr>
</tbody>
</table></div>
I want to be able to click on one row and call the appropriate function in my controller:
var AppControllers = angular.module('AppControllers', []);
AppControllers.controller('KundeDetailCtrl', ['$scope', '$routeParams', 'Kunde',
function($scope, $routeParams, Kunde) {
$scope.kunde = Kunde.get({kundeId: $routeParams.kundeId}, function(kunde) {
});
$scope.getMandant = function(id){
for(var i= 0, l=$scope.kunde.mandanten.length; i<l; i++){
if($scope.kunde.mandanten[i].id == "id")
{
$scope.mandant = $scope.kunde.mandanten[i];
}
}
Location.href='index.html#/kunden/{{kunde._id}}/module'
};
}]);
Actually, I only want to know which row was clicked and hand the object of the clicked row to the next partial which is supposed to display some other data.
The ng-click does not seem to do anything at all. In the console I only see getMandant: null
Can anyone help me with this?
It seems you are comparing the id in the mandaten list to the string "id" rather than the object id:
if($scope.kunde.mandanten[i].id == "id")
You should also consider using === rather than ==, it is the preferred way to compare things in javascript.
It appears you are redirecting to another view in your angular application, any reason not to use the $location service?

Resources