I have a pop-up message that I want to present when my observable is delivered, its a string observable.
this is my function that returns string observable:
public sendUpdate() {
this._mtService.sendCurrentUpdate(this.myList).subscribe(
res => this.messageToDisplay = res,
error => this.messageToDisplay = error
);
}
this is my function that I present the pop up with the relevant message:
public showMessageDialog(message) {
let config = new MdDialogConfig()
.title('Message:')
.textContent(message)
.ok('Got it');
this.dialog.open(MdDialogBasic, this.element, config);
}
now, I want to know where and how should I call this message to present messageToDisplay when the observable is ready.
I t would be even better if you can tell me how I can show some loader while the observable is waiting to receive the string and then when its there present it...
I tried to do this:
public sendUpdate() {
this._mtService.sendCurrentUpdate(this.myList).subscribe(
res => this.messageToDisplay = res,
error => this.messageToDisplay = error
);
this.showMessageDialog(this.messageToDisplay);
}
but what happens here is that the first time i click on update i see an empty pop-up and if I click on it again I see the pop-up with the message, its obvious that it happens because the string didnt came back yet, but how do I get over it?
thanks!
The functions you pass to subscribe() will be called later/asynchronously, hence you need to call showMessageDialog() later as well:
public sendUpdate() {
this.showLoader();
this._mtService.sendCurrentUpdate(this.myList).subscribe(
res => { this.stopLoader(); this.showMessageDialog(res); },
error => { this.stopLoader(); this.showMessageDialog(error); }
);
}
Related
I have local file where I can check if correct messages have been sent through console.
I can see the messages through cypress and count them but it seems that I can't check the actual message.
Code Example:
it(`Checking Error Text in:`, () => {
cy.visit('../testmessages.html', {
onBeforeLoad(win) {
cy.stub(win.console, 'log').as('consoleLog')},
})
cy.get('button').click()
cy.get("#consoleLog").should('be.calledThrice')
//here I would like to confirm that message contains "Id" etc
})})})
Technically, if you use cy.stub() you can't see the message in the console any more, because it blocks the call.
A cy.spy() would be better, then any console.log() you add for debugging aren't swallowed up by the stub.
If you save the result of the cy.spy(), you can use methods on it to extract the call data collected.
let spy;
Cypress.on('window:before:load', (win) => {
spy = cy.spy(win.console, 'log');
});
cy.visit('../testmessages.html')
cy.get('button').click() // console.log('hello', 'world')
cy.then(() => {
const calls = spy.getCalls();
expect(calls.length).to.eq(3)
expect(calls[1].args).to.deep.eq(['hello', 'world'])
})
With a stub, you can check what was passed to the function with something like this
cy.get(#consoleLog).should("have.been.calledWith", "Expected console message");
I have some data being fetched in an ngOnInit() for a dialog. When the dialog initially pops up, there is no data displayed. If I manually resize the browser window, it appears. If I navigate to a different tab in the popup, then back to the original, the data also appears.
My ngOnInit -
ngOnInit(): void {
this.route.params.pipe(takeUntil(this.destroy$)).subscribe( res => {
this.itemId = res.itemId;
this.getItemComponents(this.itemId);
console.log(this.itemComponents);
}
The console.log shows undefined when the page loads. I have put the same console.log in the getItemComponents method like so:-
getItemComponents {
this.itemService.getComponents.subscribe( res => {
this.itemComponents = res;
console.log(this.itemComponents);
}
The console log above logs the data I want.
Any way around this? I have tried using ngIf in my HTML and it doesn’t help.
Your console.log method at ngOnInit hook launches earlier than your getItemComponents method subscription completes, so you need to combine it in one chain. Try to use something like:
ngOnInit(): void {
this.route.params
.pipe(
takeUntil(this.destroy$),
switchMap(res => this.itemService.getComponents(res.itemId))
)
.subscribe( data => {
this.itemComponents = data;
console.log(this.itemComponents);
}
}
Every time I load the webpage, I'd have to click the logo in-order my data to fully populate the local array in my component. The data fetched is located in a local JSON file. Having to refresh the page every-single-time is fairly unprofessional/annoying.
Using Angular CLI 1.3.2
Here's where my problem lies:
#Injectable()
export class LinksService implements OnInit{
siteFile : IFile[];
constructor(private http: Http) {
this.getJSON().subscribe(data => this.siteFile = data, error =>
console.log(error));
}
public getJSON(): Observable<any> {
return this.http.get('./assets/docs/links.json')
.map((res:any) => res.json());
}
getAllIpageLinks() : IPageLink[]{
var selectedIPageLinks: IPageLink[] = new Array();
var selectedFileLinks : IFile[] = new Array();
selectedFileLinks = this.siteFile;
for (var i=0; i<selectedFileLinks.length; i++)
{
selectedIPageLinks =
selectedIPageLinks.concat(selectedFileLinks[i].files);
}
return selectedIPageLinks.sort(this.sortLinks);
}
Component:
constructor(private elRef: ElementRef, private linksService: LinksService) {
this._file = this.linksService.getAllIpageLinks();
}
Edit
The title has to be clicked in order for array of IFile[] to completely render. I've tried setting IFile to an empty array (IFile[] = []) The error goes away, however, it will render empty data.
The problem seems to be in the For loop, it can't recognize .length.
Problem :
The codes are correct but the approach is wrong. Subscribing to an Observable getJSON() is async task. Before any data is being returned by getJSON(), you already calls getAllIpageLinks() and therefore you get null value on very first run. I believe since you have injected the service as singleton in component, the data gets populated in subsequent call( on refresh by clicking logo).
Solution:
Apply the changes (that you are making in getAllIpageLinks ) by using map operator on observable.
return the instance of that observable in the component.
subscribe to that observable in the component(not in .service)
Welcome to StackOverflow. Please copy paste your codes in the question instead of giving screenshot of it. I would be able than to give you along the exact codes
Reference Codes :
I haven't tested the syntax but should be enough to guide you.
1. Refactor getAllIpageLinks() as below
public getAllIpageLinks(): Observable<any> {
return this.http.get('./assets/docs/links.json')
.map((res:any) => res.json());
.map(res => {
var selectedIPageLinks: IPageLink[] = new Array();
var selectedFileLinks : IFile[] = new Array();
selectedFileLinks = res;
for (var i=0; i<selectedFileLinks.length; i++)
{
selectedIPageLinks =
selectedIPageLinks.concat(selectedFileLinks[i].files);
}
return selectedIPageLinks.sort(this.sortLinks);
});
}
call above getAllIpageLinks() in your component
and subscribe to it there
I am using ngx-translate service for translations in my angular app. I would like to create method that would accept path to string which needs to be returned. My method looks like this:
public translateString(parameter: string): string {
let message = "";
this.translate.get(parameter).subscribe((response) => {
message = response;
});
return message;
}
But it always returns empty string, I think the problem is the subscribe call so return message gets executed before message = response. Any solutions?
The data is not synchronously available. You'll need to return the observable, and then the caller can subscribe to do what they need to do once the message is available.
public translateString(parameter: string): Observable<String> {
return this.translate.get(parameter);
}
// and then used like this:
SomeService.translateString('hello world')
.subscribe(message => {
console.log(message);
})
use instant
It not require any observables.
this.message = this.translate.instant('Language')
You need to return your message inside subscribe.Like this:
public translateString(parameter: string): string {
let message = "";
this.translate.get(parameter).subscribe((response) => {
message = response;
return message;
});
}
I have a function, that gets called twice by an observe function. As you can see, in the addMessage function, there is a check that if it is called with the same messge, it returns.
My problem is, that the addMessage function is getting called twice with the same message.
I think the reason is because it is being done quickly before the first message has been added, the second message is executed already.
What is the best way to synchronize the messages, that the first one is given time to save, before the second one is processed?
this.messages.observe({
changed: (newMessage, oldMessage) => this.addMessage(newMessage)
});
and
private addMessage(message: Message): void {
let foundMessage: Message = this.localMessageCollection.findOne({ _id: message._id });
if (foundMessage && foundMessage._id === message._id) {
console.log('addMessage(found): '+message._id+' '+message.content);
return;
}
console.log('addMessage: '+message._id+' '+message.content);
this.addLocalMessage(message);
this.chatsStorageService.addMessage(this.activeChat, message).then((messageData: Message) => {
let data = {
chat: this.activeChat,
messageString: this.messageString,
sendMessage: true
}
this.events.publish('messages:update', data);
});
}