Want to call function in child component from parent component - javascript

I have one component with name Company and from that component I am opening one popup modal, below is code for that.
Now in that popup modal user is uploading file and submit it, and then I am calling API.
Once API return success response then I want to call one function from Company component in that popup modal component.
html code
<div class="fileUploadButton">
<button color="primary" (click)="openUploadDocumentDialog()">
Add Other Documents
</button>
</div>
ts file code
public openUploadDocumentDialog() : void {
const dialogRef = this.dialog.open(UploadDocumentDialogComponent, {
width: '50vw',
panelClass: ['documentsUploadDialog', 'ceqUserDialog'],
data: {
companyid: this.route.snapshot.params['company_guid']
}
});
}
Now in this upload document dialog component user is uploading file, so once user upload file then click on Save then I am calling API.
It is successfully calling it. What I want is once this API get called successfully and returned response then I want to call method from Company component.
Upload-document-dialog.ts file
public uploadFileHandler(): void {
this.apiService.uploadDocumentFile(this.uploadedFile)
.subscribe({
next: (event) => {
if (event.data) {
**// here I want to call function from Parent company dialog.**
this.dialogRef.close(event.data);
}
},
error: (err) => {
this.snackBar.open('Connect error! Please try again!', 'Ok', {
duration: 2000,
});
},
});
}

This is the way I would go about solving the problem. I think in general it is 'bad practice' to call a function from the parent from the dialog box. So to get around this we would do the following.
Subscribe to dialogRef.afterClosed() call.
For example you could do something like this on the Company component
.html
<div class="fileUploadButton">
<button color="primary" (click)="openUploadDocumentDialog()">
Add Other Documents
</button>
</div>
.ts
public openUploadDocumentDialog() : void {
const dialogRef = this.dialog.open(UploadDocumentDialogComponent, {
width: '50vw',
panelClass: ['documentsUploadDialog', 'ceqUserDialog'],
data: {
companyid: this.route.snapshot.params['company_guid']
}
});
dialogRef.afterClosed().subscribe(response=> {
// 'response' will be 'event.data' from this.dialogRef.close(event.data)
})
}

Related

Asynchronous method doesn't work the first time

I'm new in Firebase. I'm using Firestore database and Ionic, I have this problem with an asynchronous call and I can't solve it. Basically in the item variable goes the data that I have saved in the firestore database. But when I want to show them, through a button, in a new html page a strange thing happens, in the url the passed parameter appears and disappears immediately and nothing works anymore. I had a similar problem in the past that I solved using the angular pipe "async" , but in this case it doesn't even work.
In detail, I have a list of items in a component:
ngOnInit() {
this.itemService.getItemsList().subscribe((res)=>{
this.Tasks = res.map((t) => {
return {
id: t.payload.doc.id,
...t.payload.doc.data() as TODO
};
})
});
}
and in item.service.ts I have defined the function:
constructor(
private db: AngularFireDatabase,
private ngFirestore: AngularFirestore,
private router: Router
) { }
getItemsList() {
return this.ngFirestore.collection('items').snapshotChanges();
}
getItem(id: string) {
return this.ngFirestore.collection('items').doc(id).valueChanges();
}
For each item I have a button to show the detail:
<ion-card *ngFor="let item of Tasks" lines="full">
....
<ion-button routerLinkActive="tab-selected" [routerLink]="['/tabs/item/',item.id]" fill="outline" slot="end">View</ion-button>
In component itemsDescription.ts I have:
ngOnInit() {
this.route.params.subscribe(params => {
this.id = params['id'];
});
this.itemService.getItem(this.id).subscribe((data)=>{
this.item=data;
});
}
Finally in html page:
<ion-card-header>
<ion-card-title>{{item.id}}</ion-card-title>
</ion-card-header>
<ion-icon name="pin" slot="start"></ion-icon>
<ion-label>{{item.Scadenza.toDate() | date:'dd/MM/yy'}}</ion-label>
<ion-card-content>{{item.Descrizione}}</ion-card-content>
The Scadenza and Descrizione information are shown, instead id is not. Also the url should be tabs/items/:id but when I click on the button to show the item information, the passed parameter immediately disappears and only tabs/items is displayed. If I remove the data into {{}}, the parameter from the url doesn't disappear
SOLVED
I followed this guide https://forum.ionicframework.com/t/async-data-to-child-page-with-ionic5/184197. So putting ? , for example {{item?.id}} now everything works correctly
Your nested code order not right. You will get the value of id after subscription.
Check this Code:
ngOnInit() {
this.route.params.subscribe(params => {
this.id = params['id'];
this.profileService.getItem(this.id).subscribe((data)=>{
this.item=data;
});
});
}

Calling VueJS Components after login from an external script

I have a VueJS Program where I want to provide a login. Thus this login is used one multiple platforms, it is loaded via an external server (See: mounted). It is loaded, puts elements into the mainlogin-div creating a login view and when the user clicks Login it performs a http login request to another server. When the login is successful, the external script calls done(result) or error(result) whether the login was a success or not.
But now of course how can I go back to calling Vue-stuff from there? I cant just do like this.$router.push("/coolPath") or call a defined method like loggedIn to make a toast or what not... How is this implemented?
<template>
<div id="main">
<div id="mainlogin"></div>
<script type="application/javascript">
function done(result){
console.log(result);
loggedIn(result, true)
}
function error(result) {
console.log(result)
loggedIn(result, false)
}
</script>
</div>
</template>
<script>
const Toast = require("#/toast/toast")
export default {
name: "Login",
components: {},
data() {
return {
isAuthenticated: false
}
},
beforeMount() {
let loginScript = document.createElement('script')
loginScript .setAttribute('src', 'http://**.***.***.***/index_krass.js')
document.body.appendChild(loginScript )
},
methods: {
loggedIn: function (result, success){
Toast.toast(result.message, success)
}
}
}
</script>
<style>
...
</style>
Error is always "this." is not defined or loggedIn(...) is not defined...
Maybe its some race condition where VueJS needs to be loaded first or the other way around?
Instead of the <script> block in the template, just set the global functions up on window as arrow functions to capture the Vue instance context:
export default {
beforeMount() {
window.done = result => this.loggedIn(result, true)
window.error = result => this.loggedIn(result, false)
let loginScript = document.createElement("script")
loginScript.setAttribute("src", ".../index_krass.js")
document.body.appendChild(loginScript)
},
destroyed() {
window.done = window.error = undefined
},
}
demo

How execute javascript after a component change in angular?

My code works fine when I write in browser localhost:4200/pay;id=1. This show Pay component with credit card fields generated by a external javascript (This javascript script is loaded from this component). But if i come from another component to this, Pay component doesn't show the credit card fields but load external script. How can I fix this?
My code
first.component.ts
let datos = {
id:'6'
}
this.router.navigate(['pay',datos]);
pay.component.ts
ngOnInit(): void {
this.loadScripts();
}
loadScripts() {
this.dynamicScriptLoader.load('2payjs').then(data => {
// Script Loaded Successfully
console.log('All elements loaded successfully')
this.loadElement();
}).catch(error => console.log(error));
}
loadElement(){
let that = this;
let id = this.router.snapshot.paramMap.get('id');
window.addEventListener('load', function() {
// Initialize the JS Payments SDK client.
let jsPaymentClient = new TwoPayClient('AVLRNG');
// Create the component that will hold the card fields.
let component = jsPaymentClient.components.create('card');
component.mount('#card-element');
// Handle form submission.
document.getElementById('payment-form').addEventListener('submit', (event) => {
event.preventDefault();
/// Extract the Name field value
const billingDetails = {
name: document.querySelector('#name').value
};
// Call the generate method using the component as the first parameter
// and the billing details as the second one
jsPaymentClient.tokens.generate(component, billingDetails).then((response) => {
//console.log(response.token);
let data = {
token:response.token
}
}).catch((error) => {
console.error(error);
});
});
});
}
const navigationExtras: NavigationExtras = {
queryParams: {
id: 1,
},
queryParamsHandling: 'merge'
};
this.router.navigate(['pay'], navigationExtras);
you need navigationExtras in order to create params in your router link and able to fetch by another component
Already solved. I just delete window load event listener.

Button click event is not reponding in Angular

In my .html file, I have the below code :-
Here the button Data Import appears....
<button mat-menu-item (click)="download()">
<mat-icon>cloud_download</mat-icon>
<span>Data Import</span>
</button>
In the component.ts file :-
Here I have defined the functioned to be called after the button is clicked::
constructor(
private downloadService: DownloadService
)
download(){
this.downloadService.getDownload();
}
In downloadservice.ts file :-
Here the service has been created which is going to call the api /Download at the backend.
export class DownloadService {
etext : String;
baseUrl: string = environment.apiUrl + '/Download';
constructor(private http: HttpClient) { }
getDownload() {
return this.http.get(this.baseUrl);
this.etext="The operation has been done";
}
}
When I click on the Data Import button ..nothing happens and no event is generated.
1- The second line will not be executed as first statement has a return keyword:
return this.http.get(this.baseUrl);
this.etext="The operation has been done";
2- As Martin Čuka commented below, you need to subscribe the Observable being returned by httpclient.
this.downloadService.getDownload().subscribe(resp => { // do whatever });
Nothing happens because httpClient is returning Observable you need to subscribe to it.
Add subsribe to your service
this.downloadService.getDownload().subscribe();
as for the line
this.etext="The operation has been done";
compiler will say to you it's unreachable nevertheless the real problem is in missing subscribe
export class Component {
constructor(private downloadService: DownloadService){}
download(){
this.downloadService.getDownload().subscribe(
() => {
// success code
},
(error) => {
// error code
}
);
}
}}
I think that the http request is fired.
However, you don't know when it finished because you are not subscribing to the Observable that the http.get returns.
component.ts
export class Component {
constructor(private downloadService: DownloadService){}
download(){
this.downloadService.getDownload().subscribe(
() => {
// success code
},
(error) => {
// error code
}
);
}
}
Be careful with subscription, you have to unsubscribe when the subscription finish.
https://blog.angularindepth.com/the-best-way-to-unsubscribe-rxjs-observable-in-the-angular-applications-d8f9aa42f6a0

Stripe not being called

I am trying to use Vue.js for my front end to call Stripe and create a token which then is sent to my backend. I have tested everything using plain HTML/JS and it all works fine, my issue comes in trying to use Vue.js I think my issue might be in how I am binding the stripe public key. Below is my code, and I have zero output to speak of, I get just redriected to the same page but wth ? at the end of the URL. Nothing else, console shows nothing and no error message or anything send to my back end.
template code
There is more but not related
<div class="col-md-8">
<card class='stripe-card col-md-8'
:class='{ complete }'
:stripe='stripeKey'
:options='stripeOptions'
#change='complete = $event.complete'
/>
<button class='pay-with-stripe' #click='pay' :disabled='!complete'>Submit Payment Details</button>
<br>
</div>
script section with relavent added
import { Card, createToken } from 'vue-stripe-elements-plus'
import axios from 'axios';
export default {
components: { Card },
data() {
return {
errorMessage: null,
successMessage: null,
complete: false,
stripeKey: process.env.VUE_APP_STRIPE_PUB_KEY,
stripeOptions: {
// see https://stripe.com/docs/stripe.js#element-options for details
hidePostalCode: true
},
current: {
stripe: {
plan: null,
last4: null
}
},
}
},
methods: {
pay () {
createToken().then(result => {
axios.post('/billing/updateCard', {
token: result.token,
})
.then(res => {
if(res.data.success == true) {
this.successMessage = res.data.message
console.log(res.data.message)
}
if(res.data.success == false) {
this.errorMessage = res.data.message // Display error message from server if an error exists
}
})
.catch((err) => {
if(err) console.log(err)
if(err) this.$router.push('/company/settings?success=false')
})
});
}
}
}
</script>
I have checked that the API key is actually in the data value by doing <p>{{ stripeKey }}</p> and seeing the value show up. So yes the key is there and the key is valid (tested copy/paste into my HTML/JS test)
created(){
this.key=process.env.VUE_APP_STRIPE_KEY;
}
try this, i used this piece of code in my project and it worked... the issue maybe is that your key is not yet initialized when card us rendered idk. maybe key isnt issue at all. try this and let me know if works and we will debug it together.

Categories

Resources