Uncaught TypeError: Cannot read property 'host' of undefined in Durandal when showing/closing modal dialog - durandal

Using Durandal 2.0.1 (can't update to 2.1.0 yet due to restrictions on project development) and I have an intermittent issue with the error shown in this question title.
All I'm doing is defining a custom dialog box then showing it:
var pleaseWaitModal = new modalBusy();
dialog.show(pleaseWaitModal);
And when my ajax call is finished I do:
dialog.close(pleaseWaitModal);
...and then display another modal with the results of my ajax call.
This all works perfectly IF the ajax call takes half a second to a second. If it's a quicker call then I get Uncaught TypeError: Cannot read property 'host' of undefined in my console window. The box still closes, it's just that I get a panicky project manager asking what the red error is for...
Is this purely because I'm trying to run "dialog.close()" before "dialog.show()" has properly completed in some circumstances?
The sequence of events is basically:
*user instigates action requiring a detailed modal dialog to appear with data in it
*as it takes several seconds to populate on some occasions, an interim modal dialog is shown with "please wait" in it
*once the ajax request is complete, the "pleasewait" modal is closed and the "detail" modal is shown
*so a bit like:
var pleaseWaitModal = new modalBusy();
dialog.show(pleaseWaitModal);
//set up deferred calls for ajax data and call ...
var deferredAjax = callDataFunction(myparams...);
return deferredAjax.then(function(result) {
dialog.close(pleaseWaitModal);
var detailModal = new detailModal();
detailModal.show(result);
});
So I don't think I can achieve this using the promise on the dialog.show(pleaseWaitModal) call, can I?

Are you using the promise that is returned from the dialog.close function to open your new modal? You might try this:
From your initial dialog:
dialog.show(new modal()).then(function(responseData) {
dialog.show(new pleaseWaitModal(responseData));
});
I think the problem you're running into is async timing related, which is why using the deferred works so well.
EDIT: Related to my comment below, you might look at using only one modal, and putting a loading indicator inside of it, like so:
view.html
<div data-bind="visible: isLoading">
<h1>Please wait...</h1>
<i class="icon-spin icon-spinner icon-4x"></i>
</div>
modalViewModel.js
var vm = {
isLoading: ko.observable(true)
};
vm.activate = function() {
makeAjaxCall().then(function(data) {
vm.isLoading(false);
**Do whatever you need for your ajax return**
return true;
});
});
I think that should work for what you need as an alternative.

Related

Issue when model changes within AJAX call in ngx-admin

I downloaded the latest build of ngx-admin (https://github.com/akveo/ngx-admin), and served it up locally. In the ./#core/data/users.service.ts file I have added the following method
getHeroes (): Observable<any[]> {
return this.http.get<any[]>('http://localhost:63468/api/clubs/heroes');
}
That endpoint just returns some JSON like so:
[{"id":11,"name":"Mr. Nice"},{"id":12,"name":"Mr. Nice2"},{"id":13,"name":"Mr. Nice3"},{"id":14,"name":"Mr. Nice4"},{"id":15,"name":"Mr. Nice5"},{"id":16,"name":"Mr. Nice6"},{"id":17,"name":"Mr. Nice7"},{"id":18,"name":"Mr. Nice8"},{"id":19,"name":"Mr. Nice9"},{"id":20,"name":"Mr. Nice0"}]
In ./#theme/components/header/header.component.ts I have added a click handler method:
getHero() {
this.userService.getHeroes()
.subscribe(heroes => {
debugger;
this.hero = heroes[0]
});
}
In ./#theme/components/header/header.component.html I added a button and click event like:
<button (click)="getHero()">
add hero
</button>
{{hero?.name}}
I have done this to the same example project on Angular.io (https://angular.io/tutorial/toh-pt6).
The issue is:
In the ngx-admin application, once that debugger line is hit, the this.hero = heroes[0] is properly set with the data I expect. Once the execution leaves that line of code, the view is not updated. If I inject private ref: ChangeDetectorRef, and call this.ref.detectChanges(); immediately after this.hero = heroes[0], then the view is properly updated. However, in the angular.io example of heroes, the view is properly updated within the context of the subscribe call. In that application no this.ref.detectChanges(); is required.
Is there something in the ngx-admin project that is messing up the Angular change detection?

BusyIndicator not working

Worklight busyindicator not working properly.My isssue is i'm using multipage.On page change i call adapter for webservice and call busy indicator so that it show work in progress while fetching.but what happen is page change and indicator show and hide quickly but adpater still in fetching phase and after sometime data called successfully but during these working no busy indicator shows.
var busyIndicator = null;
function wlCommonInit(){
busyIndicator = new WL.BusyIndicator();
}
This is the code i call on page change.
busyIndicatorDemo();
var viewPath = "views/add_fund_transfer.html";
WL.Page.load(viewPath,
{
onComplete: function() {
PayAnyOne_Controller.GetBranches(GetBranchesProcedureName);
busyIndicator.hide();
}
});
function busyIndicatorDemo() {
busyIndicator.show();
setTimeout(15000);
}
its seems like busyindicator doesn't work with adpater when using in multipage.
Please give me the solution or the problem in my code.
Thanks.
It seems like the problem is in the flow of the code. you're running this code basically:
show busy indicator
load page
when page has finished loading: invoke procedure (async call), and hide busyindicator.
So this generates the behavior you've reported - the busyindicator is shown and quickly hidden once the page has finished loading, even though the service is still fetching data (in an async call)
moving the busyindicator.hide to the onSuccess of the invoke procedure should solve the problem (put it also in the onFailure ...)
Hope this helps

set jqGrid page before url is called

I am looking for a way to set the page of a jqGrid to x...
My use case is someone is using my grid...
They click on a patient to edit that patient (I am not using jqGrids modal edit screen... to many modal windows already)...
When the save what they did to that patient, I want to redirect the browser back to the screen where they clicked on that patient, and back to the SAME PAGE...
The thing to keep in mind.
I am using asp.net MVC4. I call the first page via an action method. The url variable of my grid is another action in the same controller. That action is what I send my page and row variables down to. I am sure that this can be done, However, I have no idea of how to achieve it. So far I have tried to set the page variable and rows variable in my document.ready before I call the jqGrid...
tbl.jqGrid({
loadBeforeSend: function () {
page: pageFromTemp;
rows: rowFromTemp
}
});
basically I have tried different ways to do it. The above is just one of them.
I have tried to reload the grid in the document.ready. But that doesn't make any sense. Why reload the grid when you haven't given it any of the parameters it needs...
I have tried to set the variable in the beforeRequest event. I have a function that I try and set it in...
beforeRequest: function () {
if ((rowFromTemp != "") && (pageFromTemp != "")) {
$(this).trigger('reloadGrid', [{ page: pageFromTemp, rowNum: rowFromTemp, url: '/Encounters/GetAjaxPagedGridData/' }]);
//$.extend($(this).setGridParam({ page: pageFromTemp })),
//$.extend($(this).setGridParam({ rowNum: rowFromTemp })),
//$.extend($(this).setGridParam({ url: '/Encounters/GetAjaxPagedGridData/' }))
//$.trigger('reloadGrid', [{ page: pageFromTemp, rowNum: rowFromTemp, url: '/Encounters/GetAjaxPagedGridData/'}]);
}
},
But that doesn't work either. I am obviously missing something. What am I doing wrong...
Got it to change to the right page using loadComplete and $("frTable").trigger({})
But now I am getting a flashing Loading screen which indicates to me that it is still loading the data...
If I set a breakpoint in my code, I can confirm that it is loading the data. I am not doing something right here.
Load the grid in document ready, have it's datatype set to local, have it's url unassigned, and have it hidden. When you want to have it load, trigger the load after setting the parameters and then show it to the user.

jQuery: execute function on matched elements returned via Ajax

This jQuery selector matches a Rails 3 HTML form for a new model: $('form[id^="new_"]')
I'd like to have a simple focus function run each time a matching form loads. Sometimes the forms are loaded via a simple GET but also via Ajax. In the latter case, the content returned can be either HTML or escaped JS.
I was hoping jQuery would be able to match all cases via the selector, .on(), and the "load" event, but I can't seem to make that work for ANY case. Code:
$(document).ready(function() {
$('form[id^="new_"]').on("load", function(){
console.log("Matched!")
});
})
Any ideas?
Thanks Justice. I'm afraid I wasn't able to get your code to work. I'm using the following callback with the new custom event defined outside it as shown and I don't think the $('form') is triggering the event.
$('.shows-children').bind('ajax:success', function(evnt, data, status, xhr){
var boxSelector = '#' + $(this).data("shows");
$(boxSelector).html(xhr.responseText);
$('form').trigger('customevent');
});
$(document).on('customevent','form[id^="new_"]', function(){
console.log('Matched!')
});
(I'm surprised it seems more involved than expected to have jQuery act on HTML returned in an Ajax response.)
$(document).on("change","form[id^=\"new_\"]" function(){
console.log("Matched!")
});
For delegation, you want to delegate the original selector to a parent, as the event will bubble up.
However, load does NOT bubble up. In this case, change may suffice, but it'll trigger and attempt to see if the delegate is valid every time the document changes.
I would then suggest that you create a custom event after AJAX loads for the form.
Example:
$(document).on("customevent","form[id^="new_"]" function(){
console.log("Matched!")
$.ajax(url, function(response){
//success
$(document).append(response);
$('form').trigger('customevent');
});
});
HTH

JQuery Tab function not firing via JQuery templates

Hi I'm using JQuery tabs http://jqueryui.com/demos/tabs/ with search results being returned from my server with each row potentially having its own tabs depending on the search results. If the user clicks on the sorting options then the search results change including the tabs within each row returned which may or may not have tabs. In the example above you can see there are 2 records returned and the top record has tabs called Other Videos.
I have been successfully able to retrieve the resultset back from the server and the template is bulding correctly, however i cannot get the .tabs() function to fire? Does anyone have any experience with using tabs and know how I can get my tabs() function to fire?
Here is the code I use to dynamically load the template after the json result set is returned:
$(".searchBox").fadeOut("fast", function () {
$(this).html("").fadeIn("fast", function () {
$("#searchTemplate").tmpl(json.Data.SearchResults.Results).appendTo(".searchBox").fadeIn("fast");
});
});
And here is a for loop that I use to iterate over the results after the template has been loaded with the new html tabs created to try and get the .tabs() function to fire:
for(var i=0;i<json.Data.SearchResults.Results.length;i++){
if (json.Data.SearchResults.Results[i].OtherVideos.length || json.Data.SearchResults.Results[i].VideoFriends.FriendCount > 0)
{
$(document).find("div[id='tabs"+json.Data.SearchResults.Results[i].Counter+"']").tabs();
if ($(document).find("div[id='tabs"+json.Data.SearchResults.Results[i].Counter+"']").length > 0)
alert("it exists");
else
alert("it dont");
}
}
Suffice to say the alert box "it exists" appears successfully so it is finding the dynamically created html tab that the template generated however the tab itself is not being initialized by the statement:
$(document).find("div[id='tabs"+json.Data.SearchResults.Results[i].Counter+"']").tabs();
Does anybody know the reason why or what I'm missing here to get my .tabs() function to fire ...
I've examined the dynamic content and double checked the html code using firebug inspector and everything is according to how it should be the id's are correct, the #id's are there and so on, so my only conclusion is that the .tabs() function is not firing. Is this a limitation on the JQuery tabs itself? Can it not perform this type of "live" loading capability? Is there a callback function I should be using as part of loading the template itself?
Here is a picture of what is being returned after the call to the server without the tabs working:
Okay I fixed the problem, and thought I'd better give my answer for those of you who suffer a similar problem.
I should have placed my for loop inside of the same callback function as the tmpl call e.g:
$(".searchBox").fadeOut("fast", function () {
$(this).html("").fadeIn("fast", function () {
$("#searchTemplate").tmpl(json.Data.SearchResults.Results).appendTo(".searchBox").fadeIn("fast");
// For loop should go here!
});
});
I had the for loop after this block of code and the tabs() function essentially was not referencing the newly created tabs at all.