Angular is showing undefined for the data but it is working in the view - angular8

weatherData;
getDataFromApi(formData) {
this.apiService.getWeather(formData.location).subscribe(data => this.weatherData = data)
console.log(this.weatherData)
}
This is the function to get data and then store it in a local variable weatherData, a JSON file is returned from the API.
To get data in the veiw(HTML) I'm using
<p class="item1">{{ this.weatherData?.request.query }}</p>.
It works fine here but when I need to use the WeatherData for another function then it is showing that the parameters passed is undefined.

The reason is that your code will work asynchronously and the console.log() will be executed before the API call is completed.
The reason that the data is displayed in view is that you subscribed to the data and it will be streamed to the view asynchronously. The view will be updated only after the API call is complete because of subscription. So you can see the data in the view and not in the console.

Try this code and it will work fine.
ngOnInit() {
// getting data for Delhi location
this.apiService.getWeather("Delhi").subscribe(data => {
this.weatherData = data;
console.log(this.weatherData);
});
}
The reason behind undefined was code works asynchronously. While you send the request compiler move to the next line which was console.log(this.weatherData). It print the value of weather data which was undefined when declaring the variable. When response arrive compiler than assign data with this.weatherData.

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?

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

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.

EmberJS Route to 'single' getting JSONP

I'm having trouble with EmberJS to create a single view to posts based on the ID, but not the ID of the array, I actually have a ID that comes with the json I got from Tumblr API.
So the ID is something like '54930292'.
Next I try to use this ID to do another jsonp to get the post for this id, it works if you open the api and put the id, and actually if you open the single url with the ID on it, works too, the problem is:
When, on the front page for example, I click on a link to go to the single, it returns me nothing and raise a error.
But if you refresh the page you get the content.
Don't know how to fix and appreciate some help :(
I put online the code: http://tkrp.net/tumblr_test/
The error you were getting was because the SingleRoute was being generated as an ArrayController but the json response was not an Array.
App.SingleController = Ember.ObjectController.extend({
});
Further note that the model hook is not fired when using linkTo and other helpers. This because Ember assumes that if you linked to a model, the model is assumed to be as specified, and it directly calls setupController with that model. In your case, you need to still load the individual post. I added the setupController to the route to do this.
App.SingleRoute = Ember.Route.extend({
model: function(params) {
return App.TKRPTumblr.find(params.id);
},
setupController: function(controller, id) {
App.TKRPTumblr.find(id)
.then(function(data) {
controller.set('content', data.response);
});
}
});
I changed the single post template a bit to reflect how the json response. One final change I made was to directly return the $.ajax. Ember understands jQuery promises directly, so you don't need to do any parsing.
Here is the updated jsbin.
I modified: http://jsbin.com/okezum/6/edit
Did this to "fix" the refresh single page error:
setupController: function(controller, id) {
if(typeof id === 'object'){
controller.set('content', id.response);
}else{
App.TKRPTumblr.find(id)
.then(function(data) {
controller.set('content', data.response);
});
}
}
modified the setupController, since I was getting a object when refreshing the page and a number when clicking the linkTo
Dont know if it's the best way to do that :s

SafariExtension messageEvent

i'm trying to make a SafariExtension but i have some issue with the messaging Api, in fact the example in the doc don't work, this: Safari Message Proxies
so What work and what don't work ?
I can call the function on the global page from a injected script.
I can't send a response to the injected script.
here what i have:
injected:
safari.self.tab.dispatchMessage("foo", "bar");
no need more, the bug is in the global html.
global:
safari.application.addEventListener("message", function ( e ) {
if (e.name != 'foo')
return false;
e.target.page.dispatchMessage("bar", 'foo'); <-- Undefined on page ...
},false);
as i mention the 4th line on the global page always fails, so i can't send back an answer
to the injected script ...
no clue on the documentation since this is almost extracted form the doc.
You need to include a listener in the target page. For example...
safari.self.addEventListener("message", function(e) {
if(e.name == 'bar') {
alert(e.message);
// 'foo' would be alerted to the user, as it is the message content.
};
}, false);
Messages are one-way transactions, so sending a message to the global page and receiving a message on the target page are two completely separate events. A listener is needed on both sides of the exchange.

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.