AngularJS ng-show only triggering once - javascript

I have the following HTML
<div class="alert alert-danger col-sm-10 col-sm-offset-1" ng-show="showErrorMessage">
<button data-dismiss="alert" class="close" ng-click="closeErrorMessage()">
×
</button>
<i class="fa fa-check-circle"></i>
<strong>Error</strong> The following errors have occurred:
<div ng-repeat="error in createResp.Errors">{{error}}</div>
</div>
With the following inside my JavaScript
$scope.showErrorMessage = false;
$scope.search = function () {
var createOrderResp = myData.create($scope.request);
createOrderResp.$promise.then(function (r) {
$scope.createResp = r;
if ($scope.createResp.Errors.length > 0) {
$scope.showErrorMessage = true;
}
}, function (r) {
handleResourceError(r);
});
};
$scope.closeErrorMessage = function () {
$scope.showErrorMessage = false;
};
So everything works fantastic the first time through. If the response contains errors then the div is shown. However after clicking the close button closeErrorMessage() and then performing it again the error alert does not show up even though the showErrorMessage flag turns to true.

The issue is with data-dismiss. It will remove entire alert block. Therefore triggering ng-show with variable in scope won't help, since there won't be an html part, that will need triggering.

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

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 to automatically throw up a message when "Angular" {{variable}} disappears after Session DIES

I have an Angular app, the problem is, that when the {{controllername.name}} disappears for displaying the username, after session timeout, even though the warning for ngIdle comes up, the user can still refresh the screen and it keeps you on the page not taking you BACK to the login page.
The {{ctrlDash.userinfo.name}} disappears after 20 min. (See Below)
<ul class='nav'>
<li class='dropdown dark user-menu'>
<a class='dropdown-toggle' data-toggle='dropdown' href='#'>
<img width="23" height="23" alt="" src="assets/images/avatar.jpg" />
<span class='user-name'>{{ctrlDash.userInfo.name}}</span>
<b class='caret'></b>
</a>
<ul class='dropdown-menu'>
<li>
<a href='user_profile.html'>
<i class='icon-user'></i>
Profile
</a>
</li>
<li>
<a href='user_profile.html'>
<i class='icon-cog'></i>
Settings
</a>
</li>
<li class='divider'></li>
<li>
<a href='sign_in.html' target="_self">
<i class='icon-signout'></i>
Sign out
</a>
</li>
</ul>
</li>
</ul>
So, now, I want this feature in an template to "DETECT" when that happens and force the user to login again;
This is the ng-template on the same page at the bottom:
<!-- Templates for Modals -->
<script type="text/ng-template" id="warning-dialog.html">
<div class="modal-header">
<h3>You're Idle. Do Something!</h3>
</div>
<div class="modal-body" idle-countdown="countdown" ng-init="countdown=5">
<p>You'll be logged out in <span class="label label-warning">{{countdown}}</span> <span ng-pluralize="" count="countdown" when="{'one': 'second', 'other': 'seconds' }"></span>.</p>
<progressbar max="20" value="countdown" animate="true" class="progress-striped active" type="warning"></progressbar>
</div>
<div class="modal-footer">
Quick! Move your mouse and your session will reset...
</div>
</script>
<script type="text/ng-template" id="timedout-dialog.html">
<div class="modal-header">
<h3>Oh, Snap! You've Timed Out!</h3>
</div>
<div class="modal-body">
<p>
You were idle too long. Click the button below to be redirected to the login page and begin again.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger btn-small" data-ng-click="goBack()">Back To Login</button>
</div>
</script>
<!-- End Templates for Modals -->
First the TIMER detects IDLE and then the WARNING pops up and tells the user, OOPS, you need to login. But, when I hit refresh, it refreshes the page, but the {{ctrlDash.userInfo.name}} is now empty.
This is the code for ngIdle
//This is the IDLE function
$scope.started = false;
$scope.ended = false;
$scope.events = [];
$scope.idle = 20; //this is in ACTUAL seconds
$scope.timeout = 20; //this is in ACTUAL seconds
function closeModals() {
if ($scope.warning) {
$scope.warning.close();
$scope.warning = null;
}
if ($scope.timedout) {
$scope.timedout.close();
$scope.timedout = null;
}
}
$scope.$on('IdleStart', function () {
closeModals();
$scope.warning = $modal.open({
templateUrl: 'warning-dialog.html',
windowClass: 'modal-danger'
});
});
$scope.$on('IdleEnd', function () {
closeModals();
});
$scope.$on('IdleTimeout', function () {
closeModals();
$scope.timedout = $modal.open({
templateUrl: 'timedout-dialog.html',
windowClass: 'modal-danger'
});
});
$scope.start = function () {
closeModals();
Idle.watch();
$scope.started = true;
};
$scope.stop = function () {
closeModals();
Idle.unwatch();
$scope.started = false;
};
if(!angular.isDefined($scope.goBack)) {
console.log("I\'m not defined...");
if(!angular.isFunction($scope.goBack)) {
console.log("I\'m not a function...")
}
}
$scope.goBack = function _goBack() {
closeModals();
Idle.unwatch();
$window.location.href = $scope.templateViews.logout;
};
Finally: The goBack() function, within the controller = dashboardController, throws an error
Unreferenced error, goBack is NOT DEFINED.
Those are my issues. Would love to assistance, please. Thanks everyone.
I'm developing my first angular app, so not a master by any means.. I implemented a logout functionality. When the user attempts to go to any page after logging out, the controller checks for the presence of credentials, if none present, they get sent back to the login page with:
`$location.path('/login');`
--Updated from comment
I have 2 service modules (with factories). 1 - communicates with REST endpoints, 2 - deals with all my business stuff. When a user logs in, on success, I pass along the user's info to the setCreds function.
var businessService = angular.module('businessService, ['ngCookies' ]);
businessService.factory('setCreds', ['$cookies', function ($cookies) {
return function(un, pw, userRole) {
var token = un.concat(":", pw);
$cookies.creds = token;
$cookies.usersRole = userRole;
Then, the first thing I check on all my controllers, before getting any info needed for a view, is checkCreds.
if (!checkCreds()) {
$location.path('/login');
} else { ..proceed with getting stuff
My checkCreds looks like:
businessService.factory('checkCreds', ['$cookies', function ($cookies) {
return function () {
var returnVal = false;
var creds = $cookies.creds;
if (creds !== undefined && creds !== "") {
returnVal = true;
}
return returnVal;
};}]);
Be sure to inject your businessService into your app, and the service factory you want to use into your controller.

As I can do Bootstrap alert, pressing a button to change language

I have a problem, which I try to do an alert when the visitor changes the language of the web, the alert is create but disappear, because that is changing the link by:
?locale=es || ?locale=en || http://localhost:3000/pages/index?locale=en
The default is in English, but the push the button, the alert your duration is for 0.5 seconds and disappear.
As I can make the alert remains until you delete it?
Note: Im use Ruby On Rails.
My Button:
<li> <%= t('menuLen')%></li>
Code My Alert:
<div class="container">
<center>
<div class="alert alert-success" id="successChangeEN" role="alert">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>Success!</strong> Your Language is now English.
</div>
</center>
</div>
My JS:
<script>
bootstrap_alert = function() {}
bootstrap_alert.warning = function(message) {
$('#alert_placeholder').html('<div class="alert alert-success"><a class="close" data-dismiss="alert">×</a><span>'+message+'</span></div>')
}
$('#AlertEN').on('click', function() {
bootstrap_alert.warning('You change the language success!');
});
</script>
I hope to answer, thank you.
Here you have an example using cookies http://jsfiddle.net/0Lcofr6x/show/
Source Code Here: http://jsfiddle.net/0Lcofr6x/
Url is not changing due the fact fiddle does not accept dummy query string but trust me you are navigating to same page (reload).
$( document ).ready(function() {
$('#AlertEN').attr('href', window.location.href);
bootstrap_alert = function() {}
bootstrap_alert.warning = function(message) {
$('#alert_placeholder').html('<div class="alert alert-success"><button class="close" data-dismiss="alert">×</button><span>'+message+'</span></div>');
$('#alert_placeholder .close').unbind( "click" );
$('#alert_placeholder .close').on('click', function() { $('#alert_placeholder').hide();
$('.alert-success').show();
});
}
$('#AlertEN').on('click', function() {
$.cookie("changed_locale", "You change the language success!");
});
$('.alert-success').hide();
if ($.cookie("changed_locale") != null)
{
bootstrap_alert.warning('You change the language success!');
}
$.removeCookie("changed_locale");
});

Categories

Resources