Updating HTML in Angular is not working - angularjs

I am still learning angular and in my example projekt I have a problem on updating the view.
Got this in my header ....
<meta charset="UTF-8">
<title>{{ name }}</title>
And this in my body:
<body ng-controller="BodyController as body">
<input type="button" ng-click="changeTitle()" name="changeNameButton" value="change name"/>
This is my head controller:
myApp.controller('HeadController',
['$scope', 'ApplicationService', 'DataService', 'UserService', function ($scope, ApplicationService, DataService, UserService) {
var self = this;
$scope.name = ApplicationService.getTitle();
}]
);
And here is my body controller:
myApp.controller('BodyController', ['$scope', 'ApplicationService', function ($scope, ApplicationService) {
$scope.text = 'Hello, Angular fanatic.';
$scope.changeTitle = function () {
console.log('change the title');
ApplicationService.setTitle('test');
}
}]);
This is my application service
myApp.service('ApplicationService', ['ConfigurationService', function(ConfigurationService){
this.title = '';
this.setTitle = function (newTitle) {
console.log('new title (setter): ' + this.title);
this.title = newTitle
}
this.getTitle = function () {
if(this.title==''){
this.title = ConfigurationService.title + ' | ' + ConfigurationService.subtitle;
}
console.log('new title (getter): ' + this.title);
return this.title;
}
}]);
So far so good and sorry that I do not use codepen, etc. But it was not working in it, ...
My Problem: It is setting the title on initial load of the website, but not on pressing the button. The new name is set to ApplicationService.title, but header controller does not update it. Whats is wrong in this case? How can I update the title in the view...?
Regards
n00n
see the codepen for it: https://codepen.io/n00n/pen/bqaGKY

What you're doing is the equivalent of the following simple code:
//in the header controller
var name = service.getTitle();
// in the header template
display(name);
// later, in the body
service.setTitle('test');
// in the header template
display(name);
You see that this can't work: the variable name in the header controller has been initialized when the controller was created, and assigning a new value to the title stored in the service can't magically change the value of the name variable in the header controller. What you want is to display the title in the service:
<title>{{ getTitle() }}</title>
$scope.getTitle = function() {
return ApplicationService.getTitle();
};

That didn't work because you're calling getTitle method when title wasn't set. So that's it is referring to older title('undefined'). You can change your binding to
$scope.getTitle = ApplicationService.getTitle;
And then change HTML to
{{getTitle()}}
So title will get fetch from service and updated on the page on each digest cycle.
Other thing which I'd like to mention is, don't use(mix) $scope when you are using controllerAs, so then remove $scope from controller and bind data to below
var vm = this;
vm.getTitle = ApplicationService.getTitle;

Related

AngularJS ng-click doesn't work in digest cycle

Html:
<a href id="link "ng-click="print(arg)"> print </a>
Angularjs controller:
$scope.return_promise =function(arg){
return $http.post('\path');
)};
$scope.print = function(arg){
url ="other/path/"
$scope.return_promise(arg).then(function(r){
if(r){
$('#link').attr('href', url);
});
};
Problem: I checked with chrome debugger, the href actually updated, but the event doesn't trigger (i.e. not go to the url). If I click it again, it works.
If I add a statement document.getElementById('#link').click() at the end of if clause, it will prompt an error "digest cycle is in progress"
How can i solve this.
Not sure if I get your question. First, check if the code you paste is the code you wanted add here, because it has numerous errors. If you would like to replace dynamically href attribute do it like so:
<div ng-controller="SomeCtrl as ctrl">
print
</div>
(function () {
'use strict';
angular
.module('module')
.controller('SomeCtrl', SomeCtrl);
SomeCtrl.$inject = ['$scope'];
function SomeCtrl($scope) {
var vm = this;
vm.url = "#";
vm.return_promise = function (arg) {
return $http.post('/path');
};
vm.print = function (arg) {
var url = "other/path/";
vm.return_promise(arg).then(function (r) {
if (r) {
vm.url = url;
}
});
};
}
}());

ng-model returns a blank value even though the html input has value

I use MVC razor to render the model below.
#Html.HiddenFor(u => u.FormNo, new { #ng_model = "formData.formno" })
When source code is viewed, the html input has a value.
<input id="FormNum" name="FormNum" ng-model="formData.formno" type="text" value="154S00017">
but angular returns this as a blank value in the controller.
var url;
var controller = 'Inbox';
var action = 'Get_RCTS_FormHistory';
var RCTS = angular.module('RCTS', []);
RCTS.controller('historyController', function ($scope, $http) {
$scope.formData = {};
$scope.formData.formno = '';
url = "/" + controller + "/" + action + "?FormNo=" + $scope.formData.formno;
alert(url)
$http.get(url).success(function (data) {
$scope.logs = data;
});
});
And when debugged in Visual studio.
I'm fairly new to angular and this really irritates me. I tried adding a document.ready() function there on the controller but it also returned an error.
Thanks
I resolved this by assigning the value from another html input.
$scope.formData.formno = $('#FormNo').val();
and ultimately resolved it by using
#Html.HiddenFor(u => u.FormNo, new { #ng_model = "formData.formno",#ng_init=#Model.FormNo })
from Razor view.
You are not updating the value of scope variable
$scope.formData.formno = 'cakefun';

$location.path causes a full page refresh

I have a page with a link. If the user clicks on the link a popup will display, using ng-show. This is the ng-click:
<div class="adItem" ng-click="showArticleMethod(tiki._id, tiki.tikiTitle)" ng-repeat="tiki in tikis track by tiki._id">
On click a showArticleMethod gets called in the controller:
$scope.showArticleMethod = function(tikiID, article){
var title = $filter("underscoreString")(article)
$location.path(tikiID + "/" + title)
$scope.showArticle = tikiID
}
The method also changes the url to: index.html#/1/title using $location.url().
Since i want people to be able to directly link to the article i have set up this route:
$routProvider.when("/", {
templateUrl: "partials/promise.html",
controller:"tiki.controllers.promise",
reloadOnSearch:false
}).when("/:id/:title/", {
templateUrl:"partials/promise.html",
controller:"tiki.controllers.promise",
reloadOnSearch:false
}
Everything works fine except the animation (opacity:0 to opacity:1) that is set on the popup does not work.
My guess is that the url is not just changed but also reloaded so i tried adding 'reloadOnSearch:false' but that doesn't have any effect.
How can i change the url without reloading the url and keeping the css animation?
This is my full controller:
/* Controllers */
angular.module('tiki.controllers').controller("tiki.controllers.promise", ["$scope", "tikiDB", "$routeParams", "$filter", "$location", function($scope, tikiDB, $routeParams, $filter, $location){
$scope.tikis = tikiDB.query()
$scope.location = ""
$scope.showArticleMethod = function(tikiID, article){
var title = $filter("underscoreString")(article)
$location.path(tikiID + "/" + title)
$scope.showArticle = tikiID
}
$scope.hideArticleMethod = function(){
$location.path("")
$scope.showArticle = false
}
if($routeParams){
$scope.showArticle = parseInt($routeParams.id);
}
}])
The variable 'showArticle' is set to 'false' if no article is shown. It is set to the article ID if an article has to be shown. The article is shown in a popup that is activated using a class that is added to the <body> tag.
<body ng-class="{'bodyShowArticle': showArticle}" ng-view="">
If i add a $timeout then the animation works again but does a full page refresh after the timeout:
$timeout(function(){
$location.path(tikiID + "/" + title)
}, 1000)

AngularJS ng-click linking to a model

I am building a small rss reader using Express(ie Jade) and Angular. I have a dropdown menu, where the menu items are populated by a list of items in a model.
Whatever the user chooses as an item, there is a rss url attached to it and it should trigger a factory.
This is the jade part:
div.btn-group
button.btn.btn-info(type='button') {{loadButtonText}}
button.btn.btn-info.dropdown-toggle(data-toggle='dropdown')
span.caret
span.sr-only Toggle Dropdown
ul.dropdown-menu(role='menu')
li(ng-repeat='rss in RSSList')
a(href='#', ng-click="feedSrc='{{rss.url}}';loadFeed($event);") {{rss.Title}}
input.form-control(type='text', autocomplete='off', placeholder="This is where your feed's url will appear" data-ng-model='feedSrc')
This is my angular controller:
var News = angular.module('myApp', []);
News.controller('FeedCtrl', ['$scope','FeedService', function($scope, Feed){
$scope.loadButtonText = 'Choose News Feed';
$scope.RSSList = [
{Title: "CNN", url: 'http://rss.cnn.com/rss/cnn_topstories.rss'},
{Title: "Reuters", url: 'http://feeds.reuters.com/news/usmarkets'}
];
$scope.loadFeed = function (e) {
Feed.parseFeed($scope.feedSrc).then(function (res) {
$scope.loadButtonText=angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
}); }}]);
News.factory('FeedService', ['$http', function($http){
return {parseFeed: function (url){
return $http.jsonp('//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSON_CALLBACK&q='+encodeURIComponent(url));}}
}]);
It seems feedSrc in ng-click doesn't capture rss.url and can not be passed as argument to the parseFeed function.
I tried to pass rss.url directly into loadFeed, like this ng-click="loadFeed({{rss.url}});" and even ng-click="loadFeed('{{rss.url}}');" I didn't work either.
Simply pass it this way :
ng-click="loadFeed(rss.url)"
No need to use the {{ }} in ng-click
Why not to use just:
Jade:
a(href='#', ng-click="loadFeed(rss.url,$event)") {{rss.Title}}
Controller:
$scope.loadFeed = function (url, e) {
Feed.parseFeed(url).then(function (res) {
$scope.loadButtonText=angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
}); }}]);

Scope refuses to update

for some reason unknown to me, I can't get the controller scope to update the view,
even though apply is running and the scope itself has been updated.
I know that because when I console.log(data) I see its been updated.
userList directive should assign data.activeUser property on controller's scope.
its working, but the view is not updating accordingly
Link to the demo: http://jsbin.com/mojemiki/6/edit
var app = angular.module('app', []);
app.controller('myCtrl', function ($scope) {
$scope.data = {
users : [{
name : 'bob'
},{
name : 'koko'
}],
activeUser : {}
};
$scope.selectUser = function (user) {
// console is showing user data
console.log(user);
$scope.data.activeUser = user;
console.log($scope.data.activeUser);
// data.activeUser has been updated, but the view is not. why is that?
// $scope.$apply() - is not helping
// because its aleady running
};
});
app.directive('userList', function () {
return {
scope : {
users : '=',
onSelect : '&'
},
template : '<h3>in directive scope</h3>' +
'<button ng-repeat="u in users" ng-click="onSelect({ user : u })">Set Active User: {{u.name}}</button>' +
'<br/><code>{{users}}</code>'
};
});
The problem is that you are including Angular.js twice (version 1.2.1 from Cloudflare CDN and version 1.2.14 from Google CDN) and this is causing some kind of conflict. Remove one of them and it will work.
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js"></script>
Here is your fiddle.

Resources