angular.js controller as syntax template binding using $template cache service - angularjs

i have already used angular js before but now i am using controller as syntax in angular js and i am not able to bind template.
My controller code:
(function () {
angular.module("vkApp")
.controller("Feeds", Feeds);
function Feeds(FeedSetting, FeedLoader, $templateCache, $compile) {
var vm = this;
FeedSetting.initializeSetting(vm);
//functions declaration
vm.addFeed = addFeed;
// function implementations
function addFeed(text) {
return FeedLoader.loadFeed("http://rss.cnn.com/rss/edition_world.rss")
.then(function (feedData) {
console.log(feedData.data.responseData.feed);
vm.feedList = feedData.data.responseData.feed;
var feedTemplate = $templateCache.get("feedTemplate");
feedTemplate.then(function (markup) {
$compile(markup.data)(vm).appendTo(angular.element("#FeedArea"));
});
return vm.feedList;
});
}
};
})();
My template is:
<h7>{{feed.feedList.title}}</h7>
feed.html page:
<div id="rightSide" ng-controller="Feeds as feed">
<div class="news-feed-wrapper" id="FeedArea">
</div>
</div>
when the binding is performed it gives me error in console

You need to make couple of changes
1)Replace this line
$compile(markup.data)(vm).appendTo(angular.element("#FeedArea"));
with
$compile(markup.data)($scope).appendTo(angular.element("#FeedArea"));
because behind the scene your custom variable vm bind with Angular $scope. So $compile would work the same like it was using classic controller with $scope syntax
2) And in your binding replace
<h7>{{feed.feedList.title}}</h7>
with
<h7>{{vm.feedList.title}}</h7>
3) And inside Feed.html
ng-controller="Feeds as feed"
should be
ng-controller="Feeds as vm"
After the above changes it should work.

Related

Html element with AngularJS attribute generate after init AngularJS

I've AngularJS issue when there are some elements(button) generate dynamically or generate after init AngularJS. Source code below shows the button not able to trigger the ng-click attribute. Any ideas that can trigger the AngularJS attribute after init the AngularJS. Thanks.
OperationFormatter: function (value, row) {
var operations = [];
operations.push('<button class="btn-mini glyphicon glyphicon-edit" ng-
click="myFunc()" title="Shared_Edit"></button>');
return operations.join(' ');
// This function only can execute after init the AngularJS due to certain
conditions.
}
$(function () {
MyCtrl();
})
function MyCtrl($scope) {
var app = angular.module("appAffiliateInfo", []);
app.controller("ctrlBankInfo", function ($scope) {
$scope.myFunc = function () {
alert('ok');
};
});
};
I assume you're trying to dynamically insert the generated HTML code in your template.
It cannot be done this way, as AngularJS already parsed your template at "runtime" and created all its watchers.
You have to use the $compile service, like so:
// scope: the scope containing the function called by ng-click
// htmlCode: your html code (as a string)
var newElem = $compile(htmlCode)(scope);
// use the proper code here, depending on what you want to achieve with the HTML element
document.body.appendChild(newElem[0]);
When "compiled" by $compile, the HTML code is parsed in order to create the required watchers. You must make sure that you provide the correct scope to $compile, or the function intended to ng-click will never be called.

Pass value to Angular controller through ng-include

From a server side code I am loading and angular template as follows:
<div ng-include="'/views/signup.html'" onload="init('premium')"></div>
The view is, for now, the following:
<form ng-controller="AccountSignupController as controller">
</form>
The controller is simply:
function AccountSignupController($scope) {
$scope.plan = '';
$scope.init = function (plan) {
$scope.plan = plan;
console.log(plan);
};
};
On the console plan is always "undefined".
How can I pass a value to the controller through the template?
Do I need to set the controller on ng-include div and use ng-init?
The scope of the controller is inside the form where 'ng-controller' is. Thus $scope.init function is only "available" inside that form.
Both directives should be at the same level. Try moving 'ng-controller' to the div or 'ng-init' to the form (if possible).
You are instantiating your controller using the controller as binding syntax. In that case properties and functions are bound to the this of your controller instead of $scope. Functions should be called using the binding.
Your template should be:
<div ng-include="'/views/signup.html'"
ng-controller="AccountSignupController as controller"
onload="controller.init('premium')"></div>
Your controller:
function AccountSignupController() {
var self = this;
this.plan = '';
this.init = function (initString) {
self.plan = initString;
console.log(initString);
};
};
For more information on the controller as binding syntax, see the AngularJS ngController API

Why does not work two controller in Angular JS?

I have controller is named "UserController" in top of page:
<div ng-controller="UserController"><input type="text" ng-model="search"></div>
Also the same controller in bottom page from directive ng-view:
<div class="bottom" ng-controller="UserController">{{search}}</div>
Why I dont get value {{search}} in bottom part, when I fill field input in top?
Can I use one controller two times in a page?
Yes, you can use two controllers in AngularJs, Here is a demo.
What happens when I use ng-controller?
When you add ng-controller to a DOM element, angular create an instance of controller function and attaches it with that DOM, and thats why there is no two way data-binding between those divs.
How can I use data binding to share data between controllers?
You can use $rootScope variable or you can use services.
you can create service and inject in controller as dependency, so you can access its property with two way binding feature.
As said by JB Nizet, you need to have everything in the same "div".
<div ng-controller="UserController">
<input type="text" ng-model="search">
<div id="search-query">{{search}}</div>
</div>
Having the search-query at the bottom of the page is a matter of CSS, not Angular.
Controllers are not singletons. You have one controller for the top div, a second controller for the second div. One scope for the top div, one scope for the bottom div.
Both controllers have the same name, but you are ultimatally calling you controller function twice.
Some options you might want to consider to solve your problem:
Option 1) Use parent scope.
ng-model="$parent.search"
{{$parent.search}}
Option 2) Use root scope.
ng-model="$root.search"
{{$root.search}}
Option 3) Store the value in a service.
Services are singletons. If you type myService.search = $scope.search, then that value can read from the other controller.
You wont be able to watch a service variable, so perhaps you want to use the observer pattern here.
app.service("search", function() {
var listerners = [];
this.register = function(listener) {
listerners.push(listener);
};
this.update = function(searchValue) {
for(var i in listerners) {
listerners[i](searchValue);
}
};
});
app.controller("UserController", function($timeout, search){
search.register(function(searchValue) {
$timeout(function(){
$scope.search = searchValue;
});
});
$scope.$watch('search', function (newVal, oldVal, scope) {
search.update(newVal);
});
});
Option 4) Broadcast the new value.
$scope.$watch('search', function (newVal, oldVal, scope) {
$rootScope.$broadcast('search', newVal);
});
$scope.$on('search', function(event, data) {
$scope.search = data;
});
You can have multiple instances of the same controller in your page. They share the same functionality. But every instance of that controller is getting his own $scope. So in your first controller $scope.search can be 'mySearch', but the second controller won't get this, because it's another $scope.
You can do two things:
You can put the controller on a containing element, let's say the body, so both your input and your div are within the same $scope.
OR, if you want them to be seperate, you can use a service to share the search.
Your HTML:
<div ng-app="myApp">
<div ng-controller="UserController">
<input type="text" ng-model="search.mySearch"/>
</div>
<div ng-controller="UserController">
{{search.mySearch}}
</div>
</div>
Your Javascript:
var myApp = angular.module('myApp', []);
myApp.factory('Data', function(){
return { mySearch: '' };
});
myApp.controller('UserController', function( $scope, Data ){
$scope.search = Data;
});
See Fiddle

Directive with transclude, data binding not working in templateUrl

I have a directive with transclude:true. However, the data binding works when i use a template:"" but not when i use templateUrl:""
Below you can find my directive. The rsCarousel.html template contains the same code as the template"" property.
When using the template property i get the vm.carouselId on screen but not when using the templateUrl property.
Why is this?
Thx,
(function () {
'use strict';
angular.module('skynetDashboard').directive('rsCarouseli', carouseli);
function carouseli(){
var directive = {
restrict:"EA",
scope:{
carouselData:"=",
carouselId:"#",
carouselOptions:"#"
},
transclude:true,
templateUrl:"js/directive/rsCarousel.html",
//template:"<strong>ID: {{vm.carouselId}}</strong><ul ng-transclude></ul>",
bindToController:true,
controllerAs:"vm",
link:link,
controller:controller
}
return directive
function link(scope){
console.log(scope.vm)
}
controller.$inject = [""]
function controller(){
}
}
})();
That is strange, scope binding should work in both cases.
Be sure that your template file is not cached by the browser (and using an old version of it).

angular scope variable has no data

I'm pretty new to angular js but it seems like my simple code should work. Here is the html:
<body ng-app="MyHomepage">
<div ng-controller="RedditLoad">
{{a}}
<ul>
<li ng-repeat="article in a">
{{article.data.title}}
</li....
and here is my angualr_app.js:
var App = angular.module('MyHomepage', [])
function RedditLoad($scope){
$.getJSON("http://www.reddit.com/.json?jsonp=?", function(data) {
var data_array = [];
$.each(data.data.children, function(i,item){
data_array.push(item);
});
console.log(data_array);
$scope.a = data_array;
});
}
What am I doing wrong? console.log(data_array); is showing the correct values but the data wont seem to get passed to the template.
The getJSON callback isn't executed in the angular context so angular doesn't know about your changes and won't refresh the bindings. When code is called from an external source (like a jQuery event ), you have to encapsulate your scope changes in an $apply call:
$scope.$apply(function{
$scope.a = data_array;
}

Resources