angularjs: how to invoke controller based on his parent results - angularjs

I'm moving my very first steps with angularjs.
I have a controller which does a call to a service, which returns a list of urls (parent).
I would like to render a html ul for which each li is rendered by another controller (children) with its own template. I imagine something like this:
<ul ng-controller="ListCtrl">
<li ng-repeat="element in elements">
<div ng-controller="DetailCtrl">
{{oneField}} - {{anotherField}}
</div>
</li>
</ul>
The first controller is easy to implement:
myApp.controller('ListCtrl', function ($scope, $http) {
$http.get('services/elements')
.success(function(data) {
$scope.elements = data;
});
});
But for the second I have a problem, since I can't figure out how the controller could know which url use for the ajax call (DYNAMYC_URL):
myApp.controller('DetailCtrl', function ($scope, $http) {
$http.get(DYNAMYC_URL)
.success(function(data) {
$scope.element = data;
});
});
Could you please suggest me which is the best way in angular to approach this problem?
I've also considered to do many calls inside the first controller, but it doesn't seem a clean solution to me.

We will try to maintain the state of childRenderUrl function call in element while
initializing the element itself in ng-unit attribute.
Instead of DetailCtrl
We write a function renderChild defined as
$scope.renderChild =function(element)
{
$http.get(element.url)
.success(function(data) {
// add all required fields to element here
element.otherField=data.otherField;
element.sometherField=data.sometherField;
//a $scope.$digest may be required here
});
}
Your display logic would be
<ul ng-controller="ListCtrl">
<li ng-repeat="element in elements">
<div ng-init="renderChild(element)">
{{element.oneField}} - {{element.anotherField}}
</div>
</li>
</ul>
On initializing we would call the renderChild method which would
add two properties to the element object that would be aptly displayed by
expressions {{element.oneField}} - {{element.anotherField}}

Related

Why is my ng-repeat directive creating an invalid HTTP request?

Using Anguar UI-Router, I have the following state configured:
angular.module('foos').config(['$stateProvider',
function($stateProvider) {
$stateProvider.
state('seeFoos', {
url: '/foos',
templateUrl: 'modules/foos/client/views/list-foos.client.view.html',
controller: 'FoosController',
resolve: {
initialData : function(Foos) {
return Foos.query();
}
}
});
}
]);
In my view, I use ng-repeat to load some images by getting the image name from a service.
<section>
<div class="row">
<div class="col-xs-12 col-sm-6 top15"
ng-repeat-start="foo in bar">
<h4 ng-bind="foo.name"></h4>
<div class="row">
<a href="{{foo.link}}">
<img alt="{{foo.name}}" src="modules/foos/client/img/{{foo.imgName}}" class="col-xs-4" />
</a>
</div>
</div>
<div class="clearfix" ng-if="$index%2==1"></div>
<div ng-repeat-end=""></div>
</div>
</section>
Note that I ensure Foos.query() resolves before the template is loaded. The controller then loads the result to bar on the scope
angular.module('foos').controller('FoosController', ['$scope', '$stateParams', '$location', 'Foos', 'initialData',
function($scope, $stateParams, $location, Foos, initialData) {
$scope.bar = initialData;
}
]);
Everything works as expected, save for the following extra HTTP GET that returns a 404 error:
GET /modules/foos/client/img/%7B%7Bfoo.imgName%7D%7D
I don't understand why that request is being generated once I add the resolve option on the state configuration.
The main problem can be solved by using ng-src instead of src. From the documentation...
Using Angular markup like {{hash}} in a src attribute doesn't work right: The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}. The ngSrc directive solves this problem.
Secondly, your resolve function does not wait for the query to complete before completing the state load. This is by design in $resource actions...
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
If you do want it to wait, change the resolve to
resolve: {
initialData : function(Foos) {
return Foos.query().$promise;
}
}
And finally, you can simply use ng-if="$odd" instead of ng-if="$index%2==1".

data transfer between two angularjs controllers

I want to change the iframe source on runtime
<div class="pp lsv-video pp-player" id="rs" ng-controller="ctrl2">
<input type="text" style="width:0px;height:0px;display:none;" />
<iframe src="" class="lsv" marginheight="0" marginwidth="0" frameborder="0"></iframe>
</div>
when user clicks on any of the (mentioned below), teh data mentioned b.VideoSrc should be transferred to the different controller Ctrl2 and iframe source has to be changed.
<ul ng-controller="ctrl1">
<li ng-repeat="b in KeynoteSessions | filter:isBD">
<a href='#rs' class="fancybox" name='{{b.VideoSrc}}'>
<img src='{{b.ImageSrc}}' width='{{b.ImageWidth}}' height='{{b.ImageHeight}}' alt='{{b.ImageAlt}}' /><br />
{{b.Text}}
</a>
</li>
</ul>
please help me to achieve this, thanks!
there are many ways
1.You can create services and use common services to share data.
2.you can use rootscope variable.
3.angularjs $emit, $broadcast methods you can use
like
myApp.factory('Data', function () {
return { FirstName: '' };
});
myApp.controller('FirstCtrl', function ($scope, Data) {
$scope.Data = Data;
});
myApp.controller('SecondCtrl', function ($scope, Data) {
$scope.Data = Data;
});
http://jsfiddle.net/HEdJF/
check this one:Share data between AngularJS controllers
Usually I'm putting related content in the same controller (Youtube frame and "remote" together for exemple) but sometime I can't, so I pass the data through a Javascript Variable (Dont forget that your var need to be defined outside your controller )

Why this doesnt fire ng-repeat?

My HTML
ng-app and ng-controller are specified in markup earlier
<div class="statusEntry" ng-repeat="statusInput in statusInputs">
<span class="userName"> a </span>
<span class="statusMsg"> b </span>
</div>
Controller
app.controller('globalCtrl', ['$scope', function($scope) {
//someWork
pubnub.subscribe({
channel: "statuses",
callback:
function (data) {
splitData = data.split(';');
prepData = '{'+splitData[0]+','+splitData[1]+'}';
statusInputs.push(prepData);
}
});
When I push the data no new object appears.
Your Controller has no name.
You haven't declare an ng-app or ng-controller in your markup anywhere.
data should be named $scope so Angular can appropriately inject the dependency.
It doesn't look like either statusInputs or your function are part of the $scope therefore there's no way for your view to access them.
Replace
statusInputs.push(prepData);
with
$scope.statusInputs.push(prepData);
This is how you enable your views to access them.

get ng-click, on injected element, to change the class of an element already in the view?

I have a <ul> that gets populated with the server. But in that controller there is also an iframe. When the <li>'s arrive there is some disconnect between them and the iframe even though they are in the same controller.
When you click one of the li's it should change the class on the iframe but it's not. However, If I move the iframe inside of the ng-repeat that injects the iframe it works.
View
<div class="content" ng-controller="FeedListCtrl">
<ul>
<li ng-repeat="item in items">
<div data-link="{{item.link}}" ng-click="articleShowHide='fade-in'">
<div ng-bind-html="item.title" style="font-weight:bold;"></div>
<div ng-bind-html="item.description"></div>
<!-- it works if i put the iframe here -->
</div>
</li>
</ul>
<!-- doesn't work when the iframe is here -->
<iframe id="article" ng-class="articleShowHide" src=""></iframe>
</div>
Here is the controller. It does an ajax call to get the data for each <li>
Controller
readerApp.controller('FeedListCtrl', ["$scope", "$http", "FeedListUpdate", function ($scope, $http, FeedListUpdate) {
$scope.setFeed = function (url) {
$http.get('feed?id=' + FeedListUpdate.GetCurrentFeedUrl()).success(function (data) {
$scope.items = data.currentFeed.items;
});
};
}]);
When inside of an ng-repeat you are in a different scope which means you are not setting the variable you think you are. Use $parent and that should work. The syntax is:
<div data-link="{{item.link}}" ng-click="$parent.articleShowHide='fade-in'">
Side note for others finding this - sometimes adding curly brackets helps as well. For more information on ng-class see here: http://docs.angularjs.org/api/ng/directive/ngClass
An Example
In case anyone wants to see this in action, I put together an example demonstrating a few ways to set the class as well as demonstrating the issue in scope (See: http://plnkr.co/edit/8gyZGzESWyi2aCL4mC9A?p=preview). It isn't very pretty but it should be pretty clear what is going on. By the way, the reason that methods work in this example is that the scope doesn't automatically redefine them the way it does variables so it is calling the method in the root scope rather than setting a variable in the repeater scope.
Best of luck!

Angular : How to load images through XHR request in ng-repeat loop

I am trying to create a contact book in which every person can have a photo.
As I would like to display the contact before getting its photo, I would write something like
<ul>
<li ng-repeat="person in persons">{{person.firstname}} {{persone.lastname}}</li>
</ul>
I would try to call a get_photo(person) available in my scope.
<ul>
<li ng-repeat="person in persons">{{person.firstname}} {{persone.lastname}}
<img ng-src="{{get_photo(person)}}" />
</li>
</ul>
Which doesn't work because it binds the function to ng-src and call get_photo every time ng-repeat is called.
I finally tried to call get_photo when initializing the DOM element and store the result in a specific attribute photo
<ul>
<li ng-repeat="person in persons">{{person.firstname}} {{persone.lastname}}
<img ng-init="get_photo(person)" ng-src="{{person.photo}}" />
</li>
</ul>
$scope.get_photo = function (person) {
// Simple example; I will try to get an image through xhr request later...
person.photo = "http://img.blogduwebdesign.com/benjamin-sanchez/737/AngularJS.jpg";
};
Is there an easier / cleaner way to do the same ?
I also created a jsFiddle : http://jsfiddle.net/V4Mss/
Thanks a lot for your feedback !
t00f
Your last example seems fine but here is another option that keeps the view a little cleaner and doesn't cause the double $digest. Remove the initialization function from each element and use the function as a getter.
HTML
<img ng-src="{{person.photo}}" />
JavaScript
myapp.controller('controller', function ($scope) {
$scope.count = 0;
$scope.get_photo = function (person) {
return "http://img.blogduwebdesign.com/benjamin-sanchez/737/AngularJS.jpg";
};
$scope.persons = [{firstname:"toto", lastname:"TOTO", photo:$scope.get_photo()},
{firstname:"tata", lastname:"TATA", photo:$scope.get_photo()},
{firstname:"titi", lastname:"TITI", photo:$scope.get_photo()}];
});
Here is a fiddle

Resources