I have created an ionic alert to decline a request. I want the user to input a reason for declining the request before they hit confirm. I then would like to save this data into my database and have a method (declineRequest) setup to do so.
The method is working for declining the request. The issue is how to save the alert 'Notes' input field into the database, and how to make sure the declineRequest method is only run when 'confirm' is clicked.
Here is the code:
The HTML:
<ion-list>
<ion-card *ngFor="let r of requests; let i = index">
<ion-item>
<h2>{{r.userId}}</h2>
<p>{{r.requestDetail}}</p>
<p>{{r.fromDateTime}} to {{r.toDateTime}}</p>
<p>{{r.type}}</p>
</ion-item>
<ion-card-content>
<button class="approve" ion-button icon-left color="secondary" (click)="approveAlert(r.id)">
<ion-icon name="checkmark"></ion-icon>
Approve
</button>
<button class="decline" ion-button icon-left color="danger" (click)="declineAlert(r.id)">
<ion-icon name="close"></ion-icon>
Decline
</button>
</ion-card-content>
</ion-card>
</ion-list>
The TS:
declineAlert(requestId) {
const alert = this.alertCtrl.create({
title: 'Confirm Request Declined',
subTitle: 'Notes:',
inputs: [
{
name: "Note",
type: "text",
placeholder: 'Please enter reasons'
}],
buttons: [ { text:"Cancel"
},
{ text: "Confirm",
handler: data => {
console.log(JSON.stringify(data));
console.log(data.Note);
}
}],
cssClass: 'alertCustomCss'
});
alert.present();
console.log(requestId);
let notes = Note;
this.declineRequest(requestId, notes);
}
I have tried different methods but cannot seem to get the text from the decline 'notes' to save.
Any help would be greatly appreciated.
As Keval pointed out you just need to use your method inside the handler like so:
declineAlert(requestId) {
const alert = this.alertCtrl.create({
title: 'Confirm Request Declined',
subTitle: 'Notes:',
inputs: [
{
name: "Note",
type: "text",
placeholder: 'Please enter reasons'
}],
buttons: [ { text:"Cancel"
},
{ text: "Confirm",
handler: data => {
this.declineRequest(requestId, data.Note);
// additional steps like pop() page etc
}
}],
cssClass: 'alertCustomCss'
});
alert.present();
}
Try with my working code
let alert = this.alertCtrl.create({
title: 'Confirm Request Declined',
inputs: [
{
type: 'textarea',
name: 'Message',
placeholder: 'Please enter reasons',
},
],
buttons: [
{
text: 'Yes',
handler: data => {
var message = data.Message;
//Here is Api call
}
},
{
text: 'No',
role: 'cancel',
handler: data => {
var message = data.Message;
//Your logic
}
}
]
});
alert.present();
Related
I know how to ask a user for his or her user name by a popup with Vue-SweetAlert2.
<template>
<v-btn class="create-button" color="yellow" #click="alertDisplay">Create</v-btn>
<br/>
<p>Test result of createCustomer: {{ createdCustomer }}</p>
</div>
</template>
<script>
export default {
data() {
return {
createdCustomer: null
}
},
methods: {
alertDisplay() {
var customer = await this.$swal({
title: 'What is your Name?',
input: 'text',
inputPlaceholder: 'Enter your name here',
showCloseButton: true,
});
console.log(customer);
this.createdCustomer = customer;
}
}
}
</script>
With code like the one above, you can store whatever the user typed into createdCustomer, and it should be displayed on the screen after the user gives the input.
But what if I wanted to ask the user for multiple pieces of information?
For example, how do I ask for info like
"customerNumber" (also want to make sure that alphabets and numbers are combined)
"locale" (also want to make sure that the input is a collection of choices that the user chooses from, like drop down menu, rather than a text field where you can type in whatever you like)
"firstName" (also want to make sure that the name doesn't exceed 255 characters)
etc.
in a single popup?
I tried to set multiple input fields like below, but I got a warning "Unknown parameter", and this doesn't seem to be a valid way.
var customer = await this.$swal({
title: 'Fill in your personal data',
input1: 'text',
input2: 'text',
input3: 'text',
inputPlaceholder: 'Enter your name here',
showCloseButton: true,
});
And how do I check if the user has given a valid input (like the name is within 255 characters, both of alphabets and numbers are used etc)?
If I were using C or Java, I could imagine using if-statements like
if(length <= 255){
// proceed
} else {
// warn the user that the input is too long
}
somewhere in the code, but in this case I don't know how I can do a similar if-statement like thing within the popup...
[ADDITIONAL QUESTION]
Is it also possible to pass an object that consists of multiple smaller elements, like "address"?
"address": {
"street": "string",
"city": "string",
"country": "USA",
"region": "string",
"zipCode": "string"
}
As per the documentation :
Multiple inputs aren't supported, you can achieve them by using html
and preConfirm parameters. Inside the preConfirm() function you can
return (or, if async, resolve with) the custom result:
const {value: formValues} = await Swal.fire({
title: 'Multiple inputs',
html: '<input id="swal-input1" class="swal2-input">' +
'<input id="swal-input2" class="swal2-input">',
focusConfirm: false,
preConfirm: () => {
return [
document.getElementById('swal-input1').value,
document.getElementById('swal-input2').value
]
}
})
if (formValues) {
Swal.fire(JSON.stringify(formValues))
}
https://sweetalert2.github.io/
For validation you have to use the inputValidor prop like this :
const {value: ipAddress} = await Swal.fire({
title: 'Enter your IP address',
input: 'text',
inputValue: inputValue,
showCancelButton: true,
inputValidator: (value) => {
if (!value) {
return 'You need to write something!'
}
}
})
if (ipAddress) {
Swal.fire(`Your IP address is ${ipAddress}`)
}
I'm struggling with a problem using Angular and PrimeNG.
There is an Input Field for weight allowing numbers up to 150. If the typed in value is greater than 150, a Confirm Button appears below the Input Field.
If this button is clicked, the Confirm Dialog pops up, asking "Are you sure?". It contains two buttons to choose from, "Yes" and "No".
1.) Choosing "No" should close the Confirm Dialog and delete the previously typed-in value in the input field (this works). The Confirm Button shall vanish (fails).
2.) Choosing "Yes" should close the Confirm Dialog and leave the typed-in value (this works). Confirm button shall vanish (also fails).
Is it somehow possible to let the button disappear after the Confirm Dialog is closed?
test.component.html:
<div class="p-col-12 p-md-6 p-lg-5">
Weight:
<div class="ui-inputgroup">
<input pInputText type="number" id="weight" name="weight" [(ngModel)]="newTest.testWeight"
placeholder="---">
<span class="ui-inputgroup-addon">kg</span>
</div>
<div *ngIf="validateIfWeightOutsideRange()">
<div>
<p-confirmDialog key="confirmWeightTest"></p-confirmDialog>
<button type="button" (click)="confirmWeightTest()" pButton icon="pi pi-check"
label="Please confirm!">
</button>
<p-messages [value]="messagesWeightTest"></p-messages>
</div>
</div>
</div>
test.component.ts
messagesWeightTest: Message[] = [];
confirmWeightTest() {
this.confirmationService.confirm({
message: 'Are you sure?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
key: 'confirmWeightTest',
accept: () => {
this.messagesWeightTest = [{
severity: 'info', summary: 'Confirmed', detail: 'The input is correct.'}];
},
reject: () => {
this.sessionService.newTest.testWeight = null;
}
});
}
Please note: The method "validateIfWeightOutsideRange()" works, therefore I think it's unnecessary to show it here.
Here is the link to PrimeNG's documentation: https://www.primefaces.org/primeng/#/confirmdialog
Maybe you have an idea?
You can simply take one bool variable and set it on confirmDialog button click
messagesWeightTest: Message[] = [];
public weightConfirmed: boolean = false;
confirmWeightTest() {
this.confirmationService.confirm({
message: 'Are you sure?',
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
key: 'confirmWeightTest',
accept: () => {
this.messagesWeightTest = [{
severity: 'info', summary: 'Confirmed', detail: 'The input is correct.'}];
this.weightConfirmed = true;
},
reject: () => {
this.sessionService.newTest.testWeight = null;
this.weightConfirmed = true;
}
});
}
<div *ngIf="validateIfWeightOutsideRange()">
<div>
<p-confirmDialog key="confirmWeightTest"></p-confirmDialog>
<button *ngIf="!weightConfirmed" type="button" (click)="confirmWeightTest()" pButton icon="pi pi-check"
label="Please confirm!">
</button>
<p-messages [value]="messagesWeightTest"></p-messages>
</div>
</div>
I'm new to ionic and having a hard time to get data from alert inputs and showing them to another page. I'm making a button that shows alert, then you can input the time (I don't know how to use datetime in ionic) and a randomizes of number. Then showing all inputs to another page.
HTML
<ion-content padding>
<ion-grid>
<button ion-button id="id" (click)="sample;" [disabled]="disabled">1</button>
</ion-grid>
</ion-content>
TS
Ground1(bname:string){
let alert = this.alertCtrl.create({
title: 'Confirm Park',
message: 'Do you want to park this slot?',
inputs: [
{
name: 'Time',
placeholder: 'Input Time',
},
{
name: 'Code',
placeholder: 'Random Number'
},
{
name: 'Date',
placeholder: 'MM/DD/YY'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
},
{
text: 'Confirm',
handler: data => {
this.buttonColor1 = 'red'
console.log('Confirm clicked');
this.disabled = true;
console.log(JSON.stringify(data));
this.navCtrl.push(ResultPage, {result:name}, alert);
}
}
]
});
alert.present();
Alerts can also include Radios, checkboxes and text inputs , but they cannot be mixed. In addition, you can not use datetime picker in it.
Do note however, different types of "text"" inputs can be mixed, such as url, email, text, etc. If you require a complex form UI which doesn't fit within the guidelines of an alert.
If you want to use different inputs such as datetime or html inputs it is recommended that you must create the form within a modal instead.
datetime.html
<ion-header>
<ion-navbar>
<ion-title>DateTime</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label>Full Date</ion-label>
<ion-datetime displayFormat="DDDD MMM D, YYYY" min="2005" max="2100" [(ngModel)]="myFullDAte"></ion-datetime>
</ion-item>
<ion-item>
<ion-label>Time</ion-label>
<ion-datetime displayFormat="hh:mm A" [(ngModel)]="myTime"></ion-datetime>
</ion-item>
</ion-list>
</ion-content>
ts file
import { ModalController, NavParams } from 'ionic-angular';
#Component(...)
class MyPage {
constructor(public modalCtrl: ModalController) { }
presentModal() {
let myModal = this.modalCtrl.create(Datetime);
profileModal.present();
}
}
You can get the data from the fields in the confirm handler. You should be able to just pass the data variable to the next page, which should include data.Time, data.Code and data.Date.
this.navCtrl.push(ResultPage, {result: data});
On your ResultPage you can just use navParams (http://ionicframework.com/docs/api/navigation/NavParams/) to retrieve the result data that you passed.
result = this.navParams.get('result');
I have the following problem. I wanna repeat menu links. But the program doesn't create the corresponding click handler.
View:
//view is created by Angular Material
<md-menu-item ng-repeat="mItem in ::menuItems">
<md-button ng-click="mItem[action]">
<md-icon>{{ ::mItem.icon }}</md-icon>
{{ ::mItem.name }}
</md-button>
</md-menu-item>
Ctrl:
$scope.menuItems = [
{ icon: 'mode_edit', name: 'Edit', action: 'clickEdit()' },
{ icon: 'delete', name: 'Delete', action: 'clickDelete()' }
];
$scope.clickEdit = clickEdit;
$scope.clickDelete = clickDelete;
function clickEdit() {
$log.info('edit clicked');
}
function clickDelete() {
//code...
}
What I need to do to get the handlers in ngClick?
I think it's best to keep that logic in a service like this:
//view is created by Angular Material
<md-menu-item ng-repeat="mItem in ::menuItems">
<md-button ng-click="action(mItem.action)">
<md-icon>{{ ::mItem.icon }}</md-icon>
{{ ::mItem.name }}
</md-button>
</md-menu-item>
$scope.menuItems = [
{ icon: 'mode_edit', name: 'Edit', action: 'edit' },
{ icon: 'delete', name: 'Delete', action: 'delete' }
];
$scope.action = function(actionName){
// call service
}
I need to add links to the text I need translated. How can I formatMessages that have links?
Right now this is what I am trying to do:
const messages = defineMessages({
copy: {
id: 'checkout.OrderReview.copy',
description: 'Label for add card button',
defaultMessage: 'By clicking the "Place Order" button, you confirm that you have read, understood, and accept our {termsAndConditionsLink}, {returnPolicyLink}, and {privacyPolicyLink}.',
},
termsAndConditions: {
id: 'checkout.OrderReview.termsAndConditions',
description: 'Label for terms and conditions link',
defaultMessage: 'Terms and Conditions',
},
returnPolicy: {
id: 'checkout.OrderReview.returnPolicy',
description: 'Label for return policy link',
defaultMessage: 'Return Policy',
},
privacyPolicy: {
id: 'checkout.OrderReview.privacyPolicy',
description: 'Label for privacy policy link',
defaultMessage: 'Privacy Policy',
},
});
Then, in the render function:
const copy = formatMessage(messages.copy, {
termsAndConditionsLink: `${formatMessage(messages.termsAndConditions)}`,
returnPolicyLink: `${formatMessage(messages.returnPolicy)}`,
privacyPolicyLink: `${formatMessage(messages.privacyPolicy)}`,
});
return <div> { copy } </div>
This doesn't work. I get:
By clicking the "Place Order" button, you confirm that you have read, understood, and accept our [object Object], [object Object], and [object Object].
What is the correct way to accomplish this task?
First, it depends on your react-intl version.
I've made it work using react-intl v2.x (2.8 to be exact). Here's how I did:
const messages = defineMessages({
copy: {
id: 'copy',
defaultMessage: 'Accept our {TermsAndConditionsLink}',
},
termsAndConditions: {
id: 'termsAndConditions',
defaultMessage: 'Terms and conditions',
},
termsAndConditionsUrl: {
id: 'termsAndConditionsUrl',
defaultMessage: '/url',
},
});
<FormattedMessage
{...messages.copy}
values={{
TermsAndConditionsLink: (
<a href={intl.formatMessage(messages.termsAndConditionsUrl)}>
{intl.formatMessage(messages.termsAndConditions)}
</a>
),
}}
/>
For newer react-intl version, you can find your answer in the docs:
v3.x:
https://formatjs.io/docs/react-intl/upgrade-guide-3x#enhanced-formattedmessage--formatmessage-rich-text-formatting
v4.x:
https://formatjs.io/docs/react-intl/api/#formatmessage
<FormattedMessage
id="footer.table_no"
defaultMessage="Hello {link}"
values={{ link: World }}
/>
Can you use the FormattedHTMLMessage component?
const messages = defineMessages({
copy: {
id: 'checkout.OrderReview.copy',
description: 'Label for add card button',
defaultMessage: 'By clicking the "Place Order" button, you confirm that you have read, understood, and accept our {termsAndConditionsLink}, {returnPolicyLink}, and {privacyPolicyLink}.',
},
termsAndConditions: {
id: 'checkout.OrderReview.termsAndConditions',
defaultMessage: 'Terms and Conditions',
},
});
const Component = () => <FormattedHTMLMessage {...{
...messages.copy,
values: {
termsAndConditionsLink: <FormattedHTMLMessage {...messages. termsAndConditions} />
}
} />