AngularJS: Best practice to pass data to template - angularjs

I have following Service-Function, that will return data, which I want to display (notice, that the data can change any time):
myService.getData(); // Returns an array
I have to use a service, since I need this data in other controller/services too.
Now I am not sure, what the best practicse is, too display the data in a template. What I do, is:
Example 1
<li ng-repeat="item in myService.getData()">
{{item.name}}
</li>
Its working fine, but is it best practice?
I also tried following:
Example 2
// In my controller:
$scope.data = myService.getData();
// In the template
<li ng-repeat="item in data" ng-controller="myCtrl">
{{item.name}}
</li>
This does not work (on page load the data is get once into $scope.data. Any Updates are ignored). I guess I could use $watch (to watch myService.getData()). But I guess that´s slower.
What do you think? Can I call a service in a template (like example 1)?
Thank you very much!

use this as a second example(best practice):
// In my controller:
$scope.service= myService
// In the template
<li ng-repeat="item in service.getData()" ng-controller="myCtrl">
{{item.name}}
</li>

Related

How To Display the Array Response by without braces and commas in UI using Angularjs

I am getting the Array Response ["item1","item2"] from the server. but i want to display the data as item1 and item2 in one by one in UI using angularjs. So, Please give me the solution?
use ng-repeat
<span ng-repeat="item in items">{{item}}</span>
First of all, your response is wrong for your requirement I guess. I should be {"items":["veg", "rotis", "Dalu"]}, then you can assign to a scope like $scope.items = yourResponse.items; in controller and in html you can ng-repeat it like,
<span ng-repeat="item in items" ng-bind="item"></span>
and if you can't change your response, if it had to come like you mentioned, then you can do it in following way.
in controller,
var items = yourResponse.items[0];
$scope.items = items.split(',');
html same as above,
<span ng-repeat="item in items" ng-bind="item"></span>

Call another controller from inside ng-repeat

I am new to angular and I am trying to call a function from another Controller. I do not want to define an addIssue function in ItemsController which calls IssuesController.addIssue or share a service, but directly reference the IssuesController. Is there any way to do that?
Here is my sample code:
<div ng-controller="ItemsController">
<ul ng-repeat="item in items">
<li><a href ng-click="addIssue(item)">{{item.name}}</a></li>
</ul>
</div>
<div ng-controller="IssuesController">
<ul ng-repeat="issue in issues">
<li>{{issue.name}}</li>
</ul>
</div>
<script>
angular.module('app').controller("IssuesController", function () {
$scope.issues = [];
$scope.addIssue = function (item) {
// Add Issue
}
});
</script>
UPDATE:
What if I have a third base controller to help them share $scope, how will that work?
<div ng-controller="OrdersController">
<div ng-controller="ItemsController">
<ul ng-repeat="item in items">
<li><a href ng-click="addIssue(item)">{{item.name}}</a></li>
</ul>
</div>
<div ng-controller="IssuesController">
<ul ng-repeat="issue in issues">
<li>{{issue.name}}</li>
</ul>
</div>
</div>
As EliteOctagon mentioned, there are other and probably more "best practice" ways to achieve your goal but you can always do this the "dirty" way, you can use $rootScope in your ItemsController to call the addIssue(item) function on IssuesController, and since all other scopes are descendant scopes of the $rootScope you can use it in any controller.
Example: http://jsfiddle.net/choroshin/5YDJW/2/
There is, but it's such a terrible idea that you should think about it thoroughly. A much better solution would be to put that functionality into a parent controller. Obviously you have functionality that is much broader in scope (pun intended) then just that div with the IssuesController.
Provided your code is a realistic sample, then addIssue() is not even used there. So it wouldn't even make sense to put it there.
One way to directly access addIssue is:
angular.element(/*select your div*/).scope().addIssue(item);
How you select your div depends. If i has an id you can use that. If you use jQuery then you can use [ng-controller= ItemsController].
Why don't you nest the controllers? You can read the Scope Inheritance Example at http://docs.angularjs.org/guide/controller
<div ng-controller="ItemsController">
<ul ng-repeat="item in items">
<li><a href ng-click="addIssue(item)">{{item.name}}</a></li>
</ul>
<div ng-controller="IssuesController"> <!-- nested and will inherit scope -->
<ul ng-repeat="issue in issues">
<li>{{issue.name}}</li>
</ul>
</div>
</div>
so if you have a function in ItemsController
$scope.addIssue = function() {do something}
then the IssuesController will inherit the $scope and you'll be able to use that function.

Angular Js - Prefill the Search with values from input

i'm quite new to Angular JS so this is probably a easy question to answer.
I have the following code. Which displays a JSON Array with several Locations, descriptions and so on. Outputting the whole thing works. And searching the field place works also .
However as I have different pages, where I want to output only lets say all locations were place is "Canada". I thought i could just use "Canada" as value="Canada" in my input with ng-model="search.place" to output only places in "Canada" . However that does not work. It seems like ng-model causes the value to disappear. Typing in "Canada" in the input however works like a charm.
How can i overcome this? ;)
<div ng-controller="IndexCtrl">
<div class="topcoat-list__container">
<input ng-model="search.place" >
<ul class="topcoat-list">
<li class="topcoat-list__item" hm-tap="open(myApp.item_id)" ng-repeat="item in items | filter:search ">
<h2>{{ item.name }}</h2>
{{item.description}}
</li>
</ul>
</div>
</div>
EDIT: This is my Controller:
myApp.controller('IndexCtrl', function ($scope, Restangular) {
// Fetch all objects from the local JSON (see app/models/myApp.js)
$scope.items = Restangular.all('item').getList();
});
EDIT2
I found an answer:
$scope.items = $filter("filter")($scope.items, {place: "Canada"});
This works and accepts also multiple parameters as {place: "Canada", price: 10}
$scope.search.place="Canada"; in the controller should do it.
Take a look at the 4th step of the AngularJS tutorial to understand the two way databinding.

How to reverse an array in angular js without creating a filter

I am having an array in controller as follows
function FooController($scope) {
$scope.items = ["a","b","c"];
}
I used ng-repeat to show the data in items,
<div ng-app>
<div ng-controller="FooController">
<ul ng-repeat="item in items">
<li>{{item}}</li>
</ul>
</div>
</div>
I got the result as a,b,c order. I want to show it in reverse order. that means c,b,a without changing its order in the controller or without creating a filter. How to do that?
Check this link
I faced the same problem, but with an array of objects. This quick solution worked for me, but using the filter is still the best practice.
<li data-ng-repeat="item in data.slice().reverse()">
...
</li>
http://bootply.com/SgVBZvZ708
In order to avoid the writting of a custom filter, I suggest you to use this syntax :
<ul ng-repeat="item in items | orderBy:'-toString()'">
The documentation assume you sort an array of Objects but in your case there are just plain strings.
Wrap the strings in objects and use orderBy or create a new filter:
angular.module("app",[])
.filter("reverse", function(){
return function(items){
return items.slice().reverse(); // Create a copy of the array and reverse the order of the items
};
});
And use it like this:
<ul ng-repeat="item in items|reverse">
Updated fiddle (I've also updated the ng-app directive so it's passed the "app" module.)

Angularjs list and detail view

this is my basic scenario. For a list of items (summary view) i want to show details view of item that got clicked on the same page.
I took this jsfiddle example and transformed it into this jsfiddle. If you look at the behavior it does work for first time but it is not consistent.
Maybe someone can help me with this, or suggest a better approach. I would like to have a different controller for managing the list and a different controller to handle the detail view.
One way of transforming the example (provided that you want to use ngSwitch) would be:
<ul ng-controller="ListController">
<li ng-repeat="item in items" ng-controller="ItemController">
<div ng-click="open(item)">{{item.content}}</div>
</li>
<hr>
<ng-switch on="anyItemOpen()">
<div ng-switch-when="true">
<div ng-controller="ItemController">
{{opened.name}}: overlay: tweet, share, pin
</div>
<a ng-click="close()">close</a>
</div>
</ng-switch>
</ul>
And here is the working jsFiddle: http://jsfiddle.net/pkozlowski_opensource/sJdzt/4/
Your jsFiddle didn't work since you were trying to reference item created in the ngRepeat scope (and thus not available outside of the ngRepeat).

Resources