How to prefill React Hook Form with setValue? - javascript

I'm trying a simple form that has CRUD functionality.
When I click EDIT button It shows all the objects and it's fine.
editHandler func gets all things from this button:
<button
onClick={() => editHandler(discount)}
className='btn btn-info btn-sm'
data-bs-placement='top'
title='Edit Info'
>
<i className='fa fa-edit'></i>
</button>
When I console this function by passed the vlaues:
const editHandler = (e) => {
console.log(e);
}
This is the object consoled editHandler:
{
children: (3) ["Mahila", "Amira", "Badru-diin"]
date: "2020-11-22T10:49:32.296Z"
department: {_id: "5f8158396931c1c9cd164b54", name: "Inpatient"}
empId: "YH-A0184"
empName: "Abdulkadir Ahmed Mohamed"
fatherName: "Ahmed Mohamed Muuse"
hasChildren: true
husband: ""
isMale: true
isSingle: false
motherName: "Madina Ahmed Muse"
wives: [" Nuurto Abdi Ali"]
}
But when I use setValue is show only half of my objects if I click button I again it show again 70% and finilly if I click it show all:
THe finction is like this:
const editHandler = (e) => {
setValue('empId', e.empId)
setValue('empName', e.empName)
setValue('department', e.department._id)
setValue('fatherName', e.fatherName)
setValue('motherName', e.motherName)
setValue('isSingle', e.isSingle)
setValue('isMale', e.isMale)
setValue('wives', e.wives)
setValue('husband', e.husband)
setValue('hasChildren', e.hasChildren)
setValue('children', e.children)
setEdit(true)
console.log(watch())
}
The consoled result from watch():
{
department: "5f8158396931c1c9cd164b54"
empId: "YH-A0184"
empName: "Abdulkadir Ahmed Mohamed"
fatherName: "Ahmed Mohamed Muuse"
isMale: true
isSingle: false
motherName: "Madina Ahmed Muse"
}
and there is dependent values like isSingle, which show husband or wife if it's false.
What I'm doing wrong. I'm new to react-hook-form.
Help.
I found something which is causing the issue is that the dependent checkboxes like show husband if !isSingle and !isMale.
but my issue still stands I need that dependent with working code.

Related

How to pass a variable from one method to another Vue?

Below is an example of my old code which was working. This code created a confirmation screen and on conformation deleted a user. However I want to use a toast element to help create a better confirmation screen. This toast element requires the methods to be split up into onConfirm and onReject. And im wondering if there is a way to pass the variable from my deleteUser method into the onConfirm method similar to how I pass it in the code below. (.then(this.onTeacherDeleted(user))
deleteUser(user) {
if (confirm("Are you sure you want to delete: " + user.name + "?")) {
this.working = true;
axios.delete('/teachers/' + user.id)
.then(this.onTeacherDeleted(user))}
// this.$toast.add({severity: 'warn', summary: 'Are you sure?', detail: 'Are you sure you want to delete this placement?', group: 'bc'});
},
onTeacherDeleted (user) {
this.$toast.add({severity:'success', summary: user.name + 'Deleted Successfully', detail:'The teacher was successfully delted from the database', life: 3000});
window.location.reload()
}
How do I pass the user variable into the onConfirm method from the deleteUser method?
deleteUser(user) {
this.$toast.add({severity: 'warn', summary: 'Are you sure?', detail: 'Are you sure you want to delete this placement?', group: 'bc'});
},
onConfirm(user) {
this.$toast.removeGroup('bc');
this.working = true;
axios.delete('/teachers/' + user.id)
.then(this.onTeacherDeleted(user))
},
onReject() {
this.$toast.removeGroup('bc');
},
The onConfirm and onReject are both on click events that happen earlier in the code (see below) :
<button class="btn border border-success rounded-3" type="button" #click="onConfirm" this.onTeacherDeleted(user) aria-expanded="false">
<button class="btn border border-danger rounded-3" type="button" #click="onReject" aria-expanded="false">
If you show more of your code maybe i can give a better solution, but from what i can see, you can just make a variable to track which user is being deleted at the moment and set its value in the:
deleteUser(user) {
this.$toast.add({severity: 'warn', summary: 'Are you sure?', detail: 'Are you sure you want to delete this placement?', group: 'bc'});
this.userToBeDeleted = user;
},
And then just use that variable in the onConfirm:
onConfirm() {
this.$toast.removeGroup('bc');
this.working = true;
axios.delete('/teachers/' + this.userToBeDeleted.id)
.then(this.onTeacherDeleted(this.userToBeDeleted))
},

How to pass multiple user inputs and update the data in a single popup using Vue-SweetAlert2

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}`)
}

How can I update the button clicked in bootstrap-vue

I am using Bootstrap-Vue to display a table, and I've added in an extra column with an update button using vue-slot. I have this displaying fine, and I have a method being called when you click the button. Within that method I can access all the information on the item however I can't seem to find a way to access the button. I want to disable it and change the contents of it. How can I access the button element? I have created a codepen example here that shows what I have set up and need to do.
HTML
<div id='app'>
<div>{{ this.output }}</div>
<b-table hover head-variant="dark"
id="pages-table"
:items="items"
:fields="fields">
<template slot="actions" slot-scope="data">
<button class="btn btn-dark" #click="update(data)">Update</button>
</template>
</b-table>
</div>
JavaScript
new Vue({
el: "#app",
data: {
output: null,
items: [
{
id: 1,
name: "Tony"
},
{
id: 2,
name: "John"
},
{
id: 3,
name: "Paul"
}
],
fields: [
{
key: "id",
label: "ID",
sortable: true
},
{ key: "name" },
{ key: "actions" }
]
},
methods: {
update(data) {
// I need to disable the button here
this.output = data;
data.item.name = "Dave";
}
}
});
You could add a dynamic ref to the button
<button class="btn btn-dark" #click="update(data)" :ref="'btn' + data.index">Update</button>
And then just access the button by that ref
this.$refs["btn" + data.index].disabled = true
This is a codepen with the example
https://codepen.io/vlaem/pen/gNjGQE
Instead of the index you could also use the id property of your data to create the ref (data.item.id)
Though personally this doens't feel right, I think it would be better if we could track the status of all the buttons on the same or a different array, maybe like in the following example
https://codepen.io/vlaem/pen/GbBMLe

Prime-NG Confirm Dialog: Hide the Button after Confirmation

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>

How can I formatMessage with a tags (links) using react-intl?

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} />
}
} />

Categories

Resources