Programmatically closing a Durandal modal - durandal

I'm new to Durandal, so I might be taking the wrong approach to my problem.
I want to show a modal popup with a message of 'logging in...please wait' when the user has clicked the login button. I want to close the modal popup once the response is received. My attempted approach is to call a custom modal popup using Durandal's app.showModal and a view with no buttons, from the login view model. This shows the modal popup I'm after, but I haven't been able to figure out how to close the popup once the server response is received. All the examples I've seen have a button on the modal popup view that closes the popup.
Is this possible? If not, is there a better approach that will show the user something is happening and also stop the user from trying to use any other button on the view?
Here's the view model code for the login view (with extraneous code removed):
define(['services/appsecurity', 'durandal/plugins/router', 'services/utils', 'services/errorhandler', 'durandal/app', 'viewmodels/controls/activityindicator'],
function (appsecurity, router, utils, errorhandler, app, activityIndicator) {
var username = ko.observable().extend({ required: true }),
password = ko.observable().extend({ required: true, minLength: 6 }),
rememberMe = ko.observable(),
returnUrl = ko.observable(),
isRedirect = ko.observable(false),
var viewmodel = {
username: username,
password: password,
rememberMe: rememberMe,
returnUrl: returnUrl,
isRedirect: isRedirect,
appsecurity: appsecurity,
login: function() {
var credential = new appsecurity.credential(this.username(), this.password(), this.rememberMe() || false),
self = this;
activityIndicator.message = 'Logging in...please wait';
app.showModal(activityIndicator);
appsecurity.login(credential, self.returnUrl())
.fail(self.handlevalidationerrors)
.always(function() { activityIndicator.close(); });
}};
return viewmodel;
});
The appsecurity.login function is the ajax post call. The view model for the custom modal is:
define(function () {
var activityIndicator = function (message, title, options) {
this.message = message;
this.title = title || activityIndicator.defaultTitle;
this.options = options || activityIndicator.defaultOptions;
this.close = function() {
this.modal.close();
};
};
return activityIndicator;
});
When running this, I get an error on .always(function() { activityIndicator.close(); }); of close is undefined.

Note for anyone using Durandal 2.0, the above marked answer only works in earlier 1.x versions. Happy coding!

Found the problem. The viewmodel for the custom modal was wrong, so the close() method was undefined. The working viewmodel is:
define(function () {
var message = ko.observable();
var activityIndicator = {
message: message,
close: function() {
this.modal.close();
}
};
return activityIndicator;
});

Related

Nightwatch.js - How to do assertion on new browser tab

I have to test one scenario. User types desired URL to text which is linked with button. When user clicks this button, user will be directed to typed URL.
When I do assertion for new tab (Google), output is always like "localhost:8080" which is my previous tab (currentPage).
I think I should set new tab to "this" but, I could not figure it out. If you can help me, I will be appreciated.
linkTest.spec.js
module.exports = {
tags: ['component', 'linkTest'],
before: function(client, done) {
this.currentPage = client.maximizeWindow().page.linkTestPage();
this.currentPage
.navigate(client.globals.devUrl)
.waitForElementVisible('body', 60000)
.customPerform(function() {
done();
});
},
'CASE ID - Case Name'() {
let googleUrl = 'https://www.google.com/';
this.currentPage
.checkInitialElements()
.setExternalUrlText(googleUrl)
.clickLinkLabel();
// Handle with new tab
this.client.windowHandles(function(result) {
let googleTab = result.value[1]; // New Google tab index
this.switchWindow(googleTab) // Switch to Google tab
.assert.urlContains('Google'); // Verify new tab is Google
});
},
after: function(client, done) {
client.end().customPerform(done);
},
};
customPerform.js
exports.command = function(fn, callback) {
this.perform(fn);
if (typeof callback === 'function') {
callback.call(self);
}
return this; // allows the command to be chained.
};
Not sure if you've already figured out how to do this or not, but the way that I was able to is to throw the assertions for the new page into a callback function for the switchWindow function. So in your example,
// Handle with new tab
this.client.windowHandles(function(result) {
let googleTab = result.value[1]; // New Google tab index
// Switch to Google tab
this.switchWindow(googleTab, function() {
this.assert.urlContains('Google'); // Verify new tab is Google
});
});

I have created a chat application in which every ten second it takes records from database but i want to show notification at taskbar

I want to show new message notification at taskbar in asp.net MVC or in somewhere to aware user that new message have came.
You can add one Boolean column in you table namely "Seen" with default false value. when user open that message then update that value as true. so you will be easily able get not seen messages for notification. and you can show notification at the top of the page in header section.
We can show desktop notification by javascript function
function createNotification() {
var options = {
body: 'This is the body of the notification',
icon: 'stupidcodes.com.png',
dir: 'ltr'
};
var notification = new Notification("Hi there", options);
notification.onclick = function () {
window.open(document.URL);
};
}
function notifyMe() {
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
}
else if (Notification.permission === "granted") {
createNotification();
}
else if (Notification.permission !== 'denied') {
Notification.requestPermission(function (permission) {
if (!('permission' in Notification)) {
Notification.permission = permission;
}
if (permission === 'granted') {
createNotification();
}
});
}
}
first check throgh ajax function if there is any unread funtion then call this notifyMe() function

Meter.call() pass variables

I'm trying to use Meteor.call() and pass two variables in to complete the method
Template.RegisterForm.events({
'submit form': function(event) {
event.preventDefault();
var emailVar = event.target.registerEmail.value;
var passwordVar = event.target.registerPassword.value;
Meteor.call('registerUser', emailVar, passwordVar )
}
});
However when I call the method, emailVar and passwordVar do not pass through.
registerUser: function (email, password) {
var id = Accounts.createUser({
email: email,
password: password
});
}
they come up undefined??
You're calling the Meteor method fine,
var emailVar = event.target.registerEmail.value;
var passwordVar = event.target.registerPassword.value;
is likely your problematic code. event.target refers to the DOM element that initiated the event, in this case being the form. In turn, registerEmail and registerPassword will be undefined
See
https://jsfiddle.net/fqp3a1mq/ for an overview on using jQuery to grab your form data.
In the context of your specific issue, a clean solution is:
Template.form.events({
'submit form'(event) {
const $form = $(event.target);
const formData = $form.serializeArray();
const params = {};
event.preventDefault();
// loop over our form data and create a params object for our method
formData.forEach(data => {
params[data.name] = data.value;
});
Meteor.call('methodName', params);
},
});
Meteor.methods({
methodName(params) {
...
},
});
With this approach, if you have an input named registerEmail, then it will exist as params.registerEmail in your Meteor method.
Hope this helps.

Protractor not waiting for login redirect before continuing tests in AngularJS, any suggestion?

I have a standard username/password/submit button form, when the user clicks on the button the form submits with ng-submit="login.submit()" which does the login and on success redirects to the main page using ui.router ($state.go("main")).
The following test fails:
describe("login", function() {
beforeEach(function() {
var email = element(by.model("login.email"));
email.clear().sendKeys("mail");
var password = element(by.model("login.password"));
password.clear().sendKeys("pass");
var submit = element(by.id("submit"));
submit.click();
});
it("should be able to login", function() {
expect(element(by.css(".loginPage")).isPresent()).toBe(false);
expect(element(by.css(".mainPage")).isPresent()).toBe(true);
});
});
and if I try to add wait times around, I can see that the browser stays on the login page the whole time (after clicking on the button) - then I get a timeout.
After a successful login the browser receives a cookie with a token for authenticating each following request.
EDIT: with some tinkering I found out where it fails..
function login(email, pass) {
alert("it gets here");
return _auth.post({ username: email, password: pass }).then(function(data) {
alert("does not get here");
console.log("loginok, token:" +$browser.cookies().apiToken); //this should be the received token
return data;
});
}
EDIT2: the Auth service
var _auth = Restangular.withConfig(function(Configurer) {
Configurer.setBaseUrl("/");
}).service("auth/simple");
return {
login: login,
};
function login(email, pass) {
return _auth.post({ username: email, password: pass });
}
Manually everything works as expected.
#JoMendez's answer was very close but didn't work in my case. Used #DaveGray's here.
Had to wrap the isPresent() call in a function.
browser.wait(function() {
return element(by.css('.mainPage')).isPresent();
});
Try this:
it("should be able to login", function() {
browser.wait(element(by.css(".mainPage")).isPresent);//this is different from sleep, this will stop the excecution of all the protractor code that is after it, until the element is present, but it won't prevent the application of loading or if is redirecting, it will keep working.
expect(element(by.css(".loginPage")).isPresent()).toBe(false);
expect(element(by.css(".mainPage")).isPresent()).toBe(true);
});
});

Why dialog just works for the first time to open my dialog box?

I have a div (mvc4 razor):
<div onclick='dialogtrigger(this)'>send</div>
when user click on this div it goes to loading a view on popup dialog box and show it to user.
it works fine for the first time that user click it, after that when user close dialog box and want to reopen it again it gives me this error :
0x800a01b6 - JavaScript runtime error: Object doesn't
support property or method 'dialog'
I clean my browser cache and check my script file if it can not support dialog why works for the first time?
my function code:
$.ajax({
url: "OpenSendDialog",
type: "GET",
})
.done(function (result) {
$("#clientdetailmodal").html(result).dialog({
autoOpen: true, modal: true, show: {
effect: "blind",
duration: 500
}
});
});
}
in my main view:
<div id="clientdetailmodal"></div>
and my controller:
[HttpGet]
public ActionResult OpenSendDialog()
{
return view();
}
I think that a problem with your function and her scope...
look here, i hope that'll help you :
var dialogtrigger=null; // global scope
$(function() {
dialogtrigger = function (){
//replace with your ajax call
$("#clientdetailmodal").html($('#content')).dialog({
autoOpen: false, modal: true, show: {
effect: "blind",
duration: 500
}
});
}
$( "#opener" ).click(function() {
// or destruct your modal on close and re-call your ajax
$( "#clientdetailmodal" ).dialog( "open" );
});
});