AngularJS View does not update after model update - javascript

I have a <div> on my page for alert message:
<div ng-controller="PercentageOverrideController as ctrl">
<script type="text/ng-template" id="alert.html">
<div class="alert" style="background-color:#fa39c3;color:white" role="alert">
<div ng-transclude></div>
</div>
</script>
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>
<button type="button" class='btn btn-default' ng-click="addAlert()">Add Alert</button>
</div>
In my Angular controller I have a variable $scope.alerts = [ ] and function which pushes a new alert message to an array:
$scope.showSuccess = function(){
$scope.alerts.push({type: 'success', msg: 'Threshold Overrided'});
};
$scope.showError = function(){
$scope.alerts.push({type: 'danger', msg: 'Error has been happened'});
};
After I make a request and get a response, I check in debug mode that the function was invoked and that a new value was added to the array. However it does not appear on my page.
I have a test button in my div:
<button type="button" class='btn btn-default' ng-click="addAlert()">Add Alert</button>
If I press this button, the alert appears on the page. If I try to invoke the same function:
$scope.addAlert = function() {
$scope.alerts.push({msg: 'Another alert!'});
};
within the code:
$scope.showSuccess = function(){
$scope.alerts.push({type: 'success', msg: 'Threshold Overrided'});
$scope.addAlert();
};
but the alert does not appear on page.
I assume that I should trigger somehow the view to show that update on page. What do you think guys?
Thank you!

You can use $scope.apply()
$scope.showSuccess = function(){
$scope.alerts.push({type: 'success', msg: 'Threshold Overrided'});
$scope.addAlert();
$scope.apply();
};

Instead of <div ng-controller="PercentageOverrideController as ctrl">
try <div ng-controller="PercentageOverrideController">

you need to run a digest loop.
$scope.$apply()
or alternatively
$scope.$digest()
should do it.

Related

Is there any better way to show success alert message

I am trying to show Success message , once the data is updated in my application. Success function is working properly , but message is not getting generated. when I click on the save() button, small alert box will display, but message wont appear.
HTML : <div class="alert alert-success" ng-show="successmessage">{{cts.success_info}}</div>
Angular Js:
$scope.successmessage = function(){
$scope.cts = [];
$scope.cts.success_info = "Data Successfully got updated";
}
You defined successmessage as a function, but using it as a value.
If you need to display alert on success call of save function, use success function below. It creates an object with a message and isSuccess flag:
Html:
<div class="alert alert-success" ng-show="cts.isSuccess">{{ cts.message }}</div>
JS:
$scope.success = function() {
$scope.cts = {
isSuccess: true,
message: 'Data Successfully got updated'
};
}
Working demo
You can take advantage of *ngIf if want to display more then just simple string like below:
showMsg: boolean = false;
onSubmit() {
this.userService.createUser(this.addForm.value)
.subscribe( data => {
this.router.navigate(['list-user']);
this.showMsg= true;
});
}
then you can use showMsg boolean to show/hide dive like below
<div class="col-md-6">
<div ng-click=="onSubmit()">
<div class="row" *ngIf="showMsg">
<div class="col-xs-12">
<p class="alert alert-success">
<strong>Registration Success!</strong> Please click here to login!.
</p>
</div>
</div>
<button class="btn btn-success">Add user</button>
</div>
</div>
note that I am using some bootstrap classes for styling.
Yes function must return something . If you want a better option , you can use toast or popover .
Do this,
<div class="alert alert-success" ng-show='cts.showmsg == true'>{{cts.success_info}}</div>
You can use one boolean variable to show/hide message.
Angular Js:
$scope.successmessage = function(){
$scope.cts = [];
$scope.cts.success_info = "Data Successfully got updated";
$scope.cts.showmsg = true;
}
If you want to display in popup or modal, then there is best library in angular called ngDialog

Ng-click Angular JS doesn't work

In my view
<button type="button"
ng-disabled="isProcessing"
ng-click="login.ssoFacebook()"
class="button button-primary">
<span class="icon icon-social-facebook"></span>
Login Using Facebook
</button>
When I click the button facebook doesn't work
My controller
this.ssoFacebook = function(){
// intiate
ssoAuth.facebook.initiate()
.then(function(customer){
if (!customer) throw 'error system';
authService.setCurrentSession(customer, $scope);
$timeout(function() {
$scope.$emit(GLOBAL_EVENTS.SYSTEM.ACCOUNT.SESSION.LOGIN_SUCCESS);
}, 500);
// redirect or something
$state.go('products', {}, {reload: true});
})
.catch(function(error){
$scope.$emit(GLOBAL_EVENTS.SYSTEM.ACCOUNT.SESSION.LOGIN_FAILED, error);
});
};
Am I doing something wrong? thanks advance
Replace this code,
this.ssoFacebook = function(){
...
}
with,
$scope.login = {};
$scope.login.ssoFacebook = function(){
..
}
This may be the issue.
If you want use function from controller instead of scope, you need mark this in html in attribute ng-controller
ng-controller="ControllerName as login"
and below you can use
<button type="button"
ng-disabled="isProcessing"
ng-click="login.ssoFacebook()"
class="button button-primary">
<span class="icon icon-social-facebook"></span>
Login Using Facebook
</button>
Change your ng-click to
ng-click="ssoFacebook()"
and in your controller change with :
$scope.ssoFacebook = function(){
...
}

AngularJS : Communication between directives - ng-repeat not refresh

I apologize of a mess but this is the first time on stackoverflow ;)
Link to jsfiddle
http://jsfiddle.net/1u1oujmu/19/
I have problem with communication between directives and refresh ng-repeat.
I have two pages homePage and dashboardPage - on these page I have directive when I refresh page (dashboardPage) everything is working, but when I switch on homePage and I will back to dahsboardPage my problem starts occurs.
Step reproduce:
dashboardPage - reload - add new link - list-link directive is refresh new link is on list
go to homePage
back to dashboard page
try to add new link - when link is added (on server and I receives response) I call factory to store a data:
dataFactory.editData("userLinksList", result.data);
//part of factory to edit and propagation data
editData: function(name, data){
dataArray[name] = data;
$rootScope.$broadcast(name);
},
Then in directive controller I have condition to listen propagation "userLinksList" checkRootScope this is flag for only one register listener
Problem is in line:
$scope.data.links = dataFactory.getData("userLinksList");
In $scope.data.links I receives new data but I don't know why ng-repeat is not refresh
when I go to homePage and back to dashboard new link will be on list
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
homePage - on the page I have list-link directive:
<div class="columns marketing-grid">
<div class="col-md-6">
<list-link hp="true"></list-link>
</div>
</div>
dashboardPage - on the page I have this same directive without parameter:
<div class="row">
<div class="col-sm-12 col-md-8">
<list-link></list-link>
</div>
</div>
template of list-link:
<ul ng-if="data.links">
<li ng-repeat="link in data.links | filter: search" class="link-list-item" data-id="{{link.id}}">
<div class="row">
<div class="col-md-9">
<a ng-href="link.url"><h3>{{link.title}} <span>{{link.host}}</span></h3></a>
</div>
<div class="col-md-3 link-list-time text-right">
{{link.date | date : 'd/MM/yyyy' }}
</div>
<div class="col-md-12">
<blockquote ng-show="link.comment">{{link.comment}}</blockquote>
</div>
<div class="col-md-2">
<span class="link-list-counter all" title="Number of links">{{link.counterAll}}</span>
</div>
<div class="col-md-6 link-list-tags">
<span>tags:</span>
<ul ng-if="link.tags">
<li ng-repeat="item in link.tags">#{{item}}</li>
</ul>
</div>
<div class="col-md-4 text-right link-list-buttons">
<button class="btn btn-default btn-xs" title="Edit" ng-click="edit(link.id);">Edit <span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
<button class="btn btn-default btn-xs" title="Delete" ng-click="delete(link.id);">Delete <span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
</div>
</div>
</li>
</ul>
Directive list-link:
app.directive("listLink", ['path', function(path){
var path = path.url(),
checkRootScope = true;
return {
restrict : "E",
scope : {
hp : "="
},
templateUrl: path.template.listlink,
replace : true,
transclude : false,
controller : ['$rootScope', '$scope','conn', 'auth', 'loaderService','stringOperation','dataFactory', function($rootScope, $scope, conn, auth, loaderService, stringOperation,dataFactory){
var dataConenction = function(){
conn.getData(path.server.link, { params : $scope.data })
.then(function(result){
if($scope.data.all == true){
dataFactory.addData("popularLinksList",result.data);
$scope.data.links = dataFactory.getData("popularLinksList");
} else{
dataFactory.addData("userLinksList",result.data);
$scope.data.links = dataFactory.getData("userLinksList");
}
}, function(msg){
console.log(msg);
});
};
$scope.hp = (typeof $scope.hp === "undefined" ? false : $scope.hp);
$scope.path = path;
$scope.userInfo = auth.getUserInfo();
$scope.data = {
auth : $scope.userInfo,
check : false,
all : $scope.hp
};
dataConenction();
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
$scope.edit = function(id){
$rootScope.$broadcast("editLink", {"id": id});
};
$scope.delete = function(id){
var check = confirm("Are you sure you want to remove?");
if (check == true) {
conn.deleteData(path.server.link, {"params" : {auth : $scope.userInfo, id : id}})
.then(function(result){
dataFactory.editData("userLinksList",result.data.links);
$scope.data.links = dataFactory.getData("userLinksList");
dataFactory.editData("userTagsList",result.data.tags);
}, function(msg){
console.log(msg);
});
}
};
}]
}
}]);
Not sure if you already fixed it but I had a crack at it.
First the "why not working" part -
Page1 creates a new scope, lets say scope1.
Page2 creates a new scope, say scope2.
When the Page1 is clicked the data.link is set to 5 items and below code is run [scope1.data.link = 5 items] -
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
When the Page2 is clicked, it set 7 items to dataFactory and it is broadcasted to and $rootScope.on is executed to update scope2.data.links to 7 items. However scope2.data.links is still set to 5 items. This is because when $rootScope.on is executed first time the "$scope" variable within the "on" function refers to closure scope i.e scope1 and NOT scope2. So essentially when scope.data.links is set to 7 then scope.data.links is set to 7 and scope2.data.links is still set to 5.
Basically ng-view creates a new scope and if directive is part of each of the views, you would always end up having different data.link value in each of the views.
Solution:
You can fix it in two ways:
Option 1: You would be better off setting the value in scope as soon the promise is resolved instead of setting in factory and getting from it in $on listener. Atleast in this case.
http://plnkr.co/edit/IdrsO1OT9zDqdRiaSBho?p=preview
Option 2: If broadcast is really essentially I think you would have to bind the data.link to rootscope (which might not be a good practice).
http://plnkr.co/edit/VptbSKRf7crU3qqNyF3i?p=preview
and may be there are other options...

Why are the Ember component(s) for my notifications not being read/rendered?

I've been stumped on this issue all day and have exhausted all possible reasons I can think of. The problem is that my handlebar to display a notification if the user has one is not displaying.
As it is early on, I'm just testing it out by when I click 'Sign in' button, it sends a notification to the user (me in this case) just so I can see it working.
To put it simply...it doesn't work. I've attached an image showing the final result on a webpage, and it seems to comment out the handlebar line, and ignore it. And I've not a clue why.
I know the data is being read, as the other classes/componenets (the .js files, and other files) are able to return the data in the console. My 'main-header' components and 'main-footer' components renders/reads fine across all pages.
I'm also using a near-enough exact copy of another website's code that uses this. And it works perfectly. Originally I made some changes but earlier I copy-pasted everything I thought relevant, and it still didn't work.
Here is the HTML for the index.hbs (the homepage/page shown in the screenshot)
<div>
{{main-header}}
{{notification-list notifications=application.currentNotifications closeNotification='closeNotification'}}z
</div>
<!--Navbar - Home, About and Contact. Fixed position follows user down page-->
<header id="header" role="banner">
<!-- Navigation -->
</header>
<!--Main Body-->
<div class="container">
<br>
<br><br><br><br><br><br><br>
<button class="btn btn-primary btn-block btn-center" type="submit" {{action 'login'}}>
Sign In
</button>
<!--Footer containing copyright, logos and social media-->
{{main-footer}}
</div>
The Homepage's .js file;
App.IndexRoute = Ember.Route.extend({
model: function() {
}
});
App.IndexView = Ember.View.extend({
templateName: 'index'
});
App.IndexController = Ember.Controller.extend({
needs: ['application'],
currentNotifications: Ember.computed.alias("controllers.application.currentNotifications"),
actions: {
login: function() {
console.log(this.currentNotifications);
this.send( 'pushNotification', 'Message Sent', false );
}
}
});
The notification-list.hbs file (Btw, the original was made using '{{#each x in y}}' and I had to change that due to deprecation, but ultimately it should work the same I believe;
<div class="container notify">
<div class="row">
{{#each notifications as notification}}
{{#if notification.error}}
<div class="alert alert-danger">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true"
{{action 'closeAlert' notification}}>
×
</button>
<span class="glyphicon glyphicon-hand-right"></span> <strong>{{notification.title}}</strong>
<hr class="message-inner-separator">
{{#each notification.message as message}}
<p>
<b>{{message.field}}</b>{{#if message.value}}: {{message.value}}{{/if}}
</p>
{{/each}}
</div>
{{else}}
<div class="alert alert-info">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true"
{{action 'closeAlert' notification}}>
×
</button>
<span class="glyphicon glyphicon-ok"></span> <strong>{{notification.title}}</strong>
<hr class="message-inner-separator">
<p>{{format-text notification.message}}</p>
</div>
{{/if}}
{{/each}}
</div>
</div>
And the associated notificationlist's .js file;
App.NotificationListComponent = Ember.Component.extend( {
notifications: [],
lastLength: 0,
didInsertElement: function(){
if(this.notifications != null){
this.notifications.forEach(function(notification){
Ember.run.later( this, function () {
if ( this.notifications.indexOf( notification ) >= 0 ) {
this.send( 'closeAlert', notification );
}
}, 3000 );
}, this)
}
},
////DO NOT REFERENCE IN HANDLEBARS
timeout: function() {
var lastLength = this.get( 'lastLength' );
var notifications = this.get( 'notifications' );
//check it was an added notification, not a destroyed one
if ( notifications.length >= lastLength ) {
var index = notifications.length - 1;
if ( index >= 0 ) {
var notification = notifications[ index ];
Ember.run.later( this, function () {
if ( notifications.indexOf( notification ) >= 0 ) {
this.send( 'closeAlert', notification );
}
}, 3000 );
}
}
//update last length
this.set('lastLength', notifications.length);
}.observes('notifications.length'),
actions: {
closeAlert: function( notification ){
this.sendAction('closeNotification', notification);
}
}
});
Finally the app.js file. I've left some parts off that I don't think is relevant (such as the Adapter and store etc) if its needed lemme know though, but its pretty much the standard/default ones;
App.ApplicationController = Ember.Controller.extend({
currentNotifications: [],
notification: Ember.Object.extend( {
title: null,
message: null,
error: false
} ),
//Don't Call Directly, Use Route.Send to activate
pushNotification: function( message, error ) {
var currentNotifications = this.get( 'currentNotifications' );
var notification = new this.notification;
var test = error ? 'Failure' : 'Success';
notification.setProperties( {
title: test,
message: message,
error: error
} );
//Remove old message
if(currentNotifications.length >= 4) {
this.send('closeNotification', currentNotifications[0]);
}
currentNotifications.pushObject( notification );
},
closeNotification: function( notification ){
var currentNotifications = this.get( 'currentNotifications' );
var index = currentNotifications.indexOf(notification);
//remove notification
currentNotifications.removeAt(index);
},
updateCurrentPath: function() {
App.set('currentPath', this.get('currentPath'));
}.observes('currentPath')
});
The image showing the result of the above code. The highlighted line () is the line where the notification-list component is supposed to be
If this is all of your code (unmodified), it seems like you're just giving it a bad value. In the template, you pass the notifications like this:
notifications=index.currentNotifications
Again, assuming that this is all of your code, I can't see where a variable named index would come from. You should probably be using controller.currentNotifications.

How can you pass a bound variable to an ng-click function?

I have a simple delete button that will accept a string or number but won't accept an ng-model variable ( not sure if that's the correct terminology ).
<button class="btn btn-danger" ng-click="delete('{{submission.id}}')">delete</button>
Which generates:
<button class="btn btn-danger" ng-click="delete('503a9742d6df30dd77000001')">delete</button>
However, nothing happens when I click. If I hard code a variable then it works just fine. I assume I'm just not doing things the "Angular" way, but I'm not sure what that way is :)
Here's my controller code:
$scope.delete = function ( id ) {
alert( 'delete ' + id );
}
You don't need to use curly brackets ({{}}) in the ng-click, try this:
<button class="btn btn-danger" ng-click="delete(submission.id)">delete</button>
The ngClick directive binds an expression. It executes Angular code directly (as ngIf, ngChange, etc.) without the need of {{ }}.
angular.module('app', []).controller('MyCtrl', function($scope) {
$scope.submission = { id: 100 };
$scope.delete = function(id) {
alert(id + " deleted!");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<button ng-click="delete(submission.id)">Delete</button>
</div>

Categories

Resources