I'm making todo vue component. One of the fields (MySQL table todos) is enum type: priority enum('high', 'medium', 'low'). How can I make radio buttons from that field or should I use some other field type?
I added manually data property with enum field values:
data() {
return {
priorities: [{ name: 'High' }, { name: 'Medium' } , { name: 'Low' }],
}
},
Then in template dynamically created radio buttons:
<label >Priority</label>
<div v-for="(priority, index) in priorities" :key="index">
<input type="radio" :name="priority.name" :value="priority.name" v-model="form.priority" :id="priority.name">
<label :for="priority.name">{{ priority.name }}</label>
</div>
I want to get default values from enum field.
Related
I have a fix number of checkbox which I am binding using for loop.
<ul>
<li *ngFor="let chk of checkboxes">
<input type="checkbox" [id]="chk.id" [value]="chk.value"/>
<label [for]="chk.id">{{chk.name}}</label>
</li>
</ul>
what I am looking for is using template driven form to get a value all of selected checkboxes, something like following
{
selected:[
checkboxValue1,
checkboxValue2,
checkboxValue3,
]
}
NOTE:
I am able to use Reactive form to generate a FormGroup->FormArray which generates the following form value
{
checkboxes:[
{
id: checkboxId1,
value: checkboxValue1,
selected: true,
},
{
id: checkboxId2,
value: checkboxValue2,
selected: false,
},
{
id: checkboxId3,
value: checkboxValue3,
selected: true,
}
]
}
Which I am then filtering out with selected==true.
I was wondering how to do something similar with template driven form.
You can attach a template variable to the checkbox and then query it using #ViewChildren
<ul>
<li *ngFor="let chk of checkboxes">
<input #checkbox type="checkbox" [id]="chk.id" [value]="chk.value"/>
<label [for]="chk.id">{{chk.name}}</label>
</li>
</ul>
Then in your component class:
export class MyComponent {
#ViewChildren('checkbox')
checkboxes!: QueryList<ElementRef>
}
And to access your array:
const selected = this.checkboxes
.map(t => t.nativeElement)
.map(checkbox => checkbox.checked
I am working on the front page of a website, in this context on the signup/login form combo. Those forms use the native forms from mobx-react, composed of a form.js observer, giving each element it's DOM structure, and a corresponding template.js file defining the role of each field. That means I can make nondescript fields in form.js and define them in template.js.
Sadly, one of my fields is being converted into a password input when nothing should make it one.
Here's a snip from form.js
export default observer(({ form }) => {
const isSuccess = state => (!state ? 'is-success' : 'is-danger');
return (
<article className='tiles is-ancestor is-inline-flex drc-column'>
<div className='tile is-vertical is-size-4 has-text-centered has-text-grey'>Inscription</div>
<form className='tile is-parent is-vertical'>
// good field
<div className='tile is-child'>
<label className='has-text-centered is-block' htmlFor={form.$('surname').id}>
{form.$('surname').label}
<input className={`input is-medium has-background-white-ter ${form.$('surname').isEmpty ? '' : isSuccess(form.$('surname').error)}`} id='signup-surname' {...form.$('surname').bind()} />
</label>
<p className='has-text-danger'>{form.$('surname').error}</p>
</div>
// multiple good fields
<button className='tile is-child button is-large has-background-success is-fullwidth has-text-white' type='submit' onClick={form.onSubmit}><span className='is-size-6 is-uppercase'>Je m'inscris</span></button>
<p className={form.error ? 'has-text-danger' : 'has-text-success'}>{form.error}</p>
</form>
</article>
);
});
and here's the other side of the coin, on template.js
setup() {
return {
fields: [{
name: 'name',
label: 'Prénom',
rules: 'required|string'
}, {
name: 'surname',
label: 'Nom',
rules: 'required|string'
}, {
name: 'company',
label: 'Entreprise',
rules: 'required|string'
}, {
name: 'phone',
label: 'Numéro de téléphone',
rules: 'required|numeric'
}, {
name: 'email',
label: 'E-mail',
rules: 'required|email|string'
}, {
name: 'password',
label: 'Mot de passe',
rules: 'required|string',
type: 'password'
}]
};
}
Here are a screenshot of the form itself, and of the actual interpreted HTML.
I want that surname field to be a regular text input, not a password input.
I can't redo the tech stack at this point to exclude using the forms from mobx-react, and it used to work just fine. Nothing is overwriting those input fields, those two snips are the only ones in control, I'm not sure where to look next.
Good day!
Issue was resolved.
When you were redirected (manually or otherwise) from the login form to the signup form, the fields were not reset. Since the second field on the login form was a password, it transitioned into the second field of the signup form, keeping the password type.
Resetting said fields with the componentWillUnmount mobx hook effectively fixes this issue:
componentWillUnmount() {
const { profileStore } = this.props;
profileStore.resetFields();
}
And into profileStore itself:
#observable fields = undefined;
#action
resetFields() {
log.warn('resetFields');
this.fields = undefined;
}
Now forms are effectively recreated from the ground up every time, no more problem.
Just made some slight changes, this should work now dude :)))))
export default observer(({ form }) => {
const isSuccess = state => (!state ? 'is-success' : 'is-danger');
return (
Inscription
// good field
{form.$('surname').label}
{form.$('surname').error}
// multiple good fields
Je m'inscris
<p className={form.error ? 'has-text-danger' : 'has-text-success'}>{form.error}</p>
</form>
</article>
);
});
I am using Vue-multiselect with Laravel.
I am using the multiselect component in my form to let the user select multiple countries. The component works fine but when I submit the form and I dd() it, it shows [object Object].
I can't get the value of the multiselect component. I have found similar questions but none of them worked for me.
Here is my code:
The ExampleComponent.vue file:
<template slot-scope="{ option }">
<div>
<label class="typo__label">Restricted country</label>
<multiselect
v-model="internalValue"
tag-placeholder="Add restricted country"
placeholder="Search or add a country"
label="name"
name="selectedcountries[]"
:options="options"
:multiple="true"
track-by="name"
:taggable="true"
#tag="addTag"
>
</multiselect>
<pre class="language-json"><code>{{ internalValue }}</code></pre>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
// register globally
Vue.component('multiselect', Multiselect)
export default {
components: {
Multiselect
},
props: ['value'],
data () {
return {
internalValue: this.value,
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
}
},
watch: {
internalValue(v){
this.$emit('input', v);
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
},
}
</script>
Here is my register form:
<div id="select">
<example-component v-model="selectedValue"></example-component>
<input type="hidden" name="countriespost" :value="selectedValue">
</div>
<script>
const select = new Vue({
el: '#select',
data: {
selectedValue: null
},
});
</script>
When I submit the form, the countriespost shows me me this: [object Object] instead of the actual value.
It's because you are providing an array of objects as options property:
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
so the value emited on input is an object.
Try to change the options to following:
options: [ 'Hungary', 'USA', 'China' ]
If you pass an array of objects to the :options prop of the multiselect component, you should submit the form with javascript so you can extract the object ids or whatever you need on the backend and then send them through.
Add a method like this:
submit: function() {
let data = {
objectIds: _.map(this.selectedOptions, option => option.id), //lodash library used here
// whatever other data you need
}
axios.post('/form-submit-url', data).then(r => {
console.log(r);
});
}
Then trigger it with a #click.stop event on your submit button.
I have a reactive form with 4 inputs type radio and 4 inputs type text.
I want to display dynamically inputs text following the radio buttons
selected. For example, if button radio 1 selected, i want to display
its corresponding input text 1.
I encounter 2 problems :
The first radio button is not selected by default (even with attribute checked) and all the radio buttons can be selected at the same time.
All the inputs text are displayed, i don't know with a *ngIf how to
check if the radio button corresponding to the input is selected.
component.html :
<section class="CreateItem" *ngIf="formGroupItemSelection">
<form (ngSubmit)="addItem()" [formGroup]="formGroupItemSelection">
<input formControlName="refNumber" type="radio" value="refNumber" checked> ref number
<br>
<input formControlName="partNumber" type="radio" value="partNumber"> part number
<br>
<input formControlName="itemName" type="radio" value="itemName"> item name
<br>
<input formControlName="manufacturerName" type="radio" value="manufacturerName">manufacturer name
<br>
<div *ngIf="formGroupItemSelection.controls.refNumber.valid">
<input list="refNumbers" formControlName="refNumberSelected" type="text" name="refNumberSelected">
<datalist id="refNumbers">
<option *ngFor="let ref of listOfItems">{{ref.refNumber.input}}</option>
</datalist>
</div>
<div *ngIf="formGroupItemSelection.controls.partNumber.valid">
<input list="partNumbers" formControlName="partNumberSelected" type="text" name="partNumberSelected">
<datalist id="partNumbers">
<option *ngFor="let ref of listOfItems">{{ref.partNumber.input}}</option>
</datalist>
</div>
<div *ngIf="formGroupItemSelection.controls.itemName.valid">
<input list="itemsName" formControlName="itemNameSelected" type="text" name="itemNameSelected">
<datalist id="itemsName">
<option *ngFor="let ref of listOfItems">{{ref.itemDesignation.input}}</option>
</datalist>
</div>
<div *ngIf="formGroupItemSelection.controls.manufacturerName.valid">
<input list="manufacturersName" formControlName="manufacturerNameSelected" type="text" name="manufacturerNameSelected">
<datalist id="manufacturersName">
<option *ngFor="let ref of listOfItems">{{ref.manufacturerName.input}}</option>
</datalist>
</div>
<button type="submit [disabled]="!formGroupItemSelection.valid">Valider</button>
</form>
</section>
component.ts :
import { Component, OnInit } from '#angular/core';
import {FormControl, FormGroup, FormBuilder, Validators} from '#angular/forms'
import { ManagementArbologistiqueService } from '../../management-arbologistique.service';
import { ActivatedRoute, Params } from '#angular/router';
import { matchValuesRefNumber, matchValuesPartNumber, matchValuesItemName, matchValuesManufacturerName } from '../Validators/validators';
#Component({
selector: 'app-item-selection',
templateUrl: './item-selection.component.html',
styleUrls: ['./item-selection.component.css']
})
export class ItemSelectionComponent implements OnInit {
formGroupItemSelection:FormGroup;
listOfItems = [];
constructor(public fb:FormBuilder,private managementArbo: ManagementArbologistiqueService, private route: ActivatedRoute) { }
ngOnInit() {
this.getListBdd();
}
initializeForm() {
this.formGroupItemSelection = this.fb.group({
refNumber : '',
partNumber: '',
itemName: '',
manufacturerName: '',
refNumberSelected:[
null,
Validators.compose([Validators.required, matchValuesRefNumber(this.listOfItems)])
],
partNumberSelected:[
null,
Validators.compose([Validators.required, matchValuesPartNumber(this.listOfItems)])
],
itemNameSelected: [
null,
Validators.compose([Validators.required, matchValuesItemName(this.listOfItems)])
],
manufacturerNameSelected:[
null,
Validators.compose([Validators.required, matchValuesManufacturerName(this.listOfItems)])
]
})
}
getListBdd() {
this.route.params.subscribe((params: Params) => {
let subroute = "getRefNumber";
this.managementArbo.getProducts(subroute)
.subscribe(
res => {
this.listOfItems = res; console.log('bdd:' + res);
this.initializeForm();
},
err => console.log(err),
() => console.log('getProducts done'));
});
}
addItem() {
}
1.-NOT use "checked". just when you create the form give the correct value. And the correct value is not "true"
this.formGroupItemSelection = this.fb.group({
refNumber : ['refNumber'], //NOT is true or false
partNumber: [],
itemName: []
....
})
2.-When we make a *ngIf into a reactive form use myform.get('mycontrol'), e.g.
<div *ngIf="formGroupItemSelection.get('partNumber').valid">...</div>
I solved my problem !
Firstly, I found important information in the angular doc to answer my first question :
"To use radio buttons in a template-driven form, you'll want to ensure that radio buttons in the same group have the same name attribute. Radio buttons with different name attributes do not affect each other.".
Then, in the case of a reactive form :
"When using radio buttons in a reactive form, radio buttons in the same group should have the same formControlName. You can also add a name attribute, but it's optional."
So, i gave the same formControlName at each radio button and the mention "checked" works now.
Otherwise, to answer my second question, I identified each radio buttons following the "value" property of input, and checked if radio buttons selected :
<div *ngIf="formGroupItemSelection.controls.radioBoutton.value==='refNumber'">
Hope it can help !
initializeForm() {
this.formGroupItemSelection = this.fb.group({
refNumber : new FormControl(true),
partNumber: new FormControl(false),
itemName: new FormControl(false),
manufacturerName: '',
refNumberSelected:[
null,
Validators.compose([Validators.required, matchValuesRefNumber(this.listOfItems)])
],
partNumberSelected:[
null,
Validators.compose([Validators.required, matchValuesPartNumber(this.listOfItems)])
],
itemNameSelected: [
null,
Validators.compose([Validators.required, matchValuesItemName(this.listOfItems)])
],
manufacturerNameSelected:[
null,
Validators.compose([Validators.required, matchValuesManufacturerName(this.listOfItems)])
]
})
//This will set the radio button checked no need to add checked attribute you can set cheked dynamically
this.formGroupItemSelection.get('refNumber ').setValue(true);
this.formGroupItemSelection.get('partNumber').setValue(true);
this.formGroupItemSelection.get('itemName').setValue(true)
}
Example based on Aurelia doc.
Page code:
export class MyPage {
products = [
{ id: 0, name: 'Motherboard' },
{ id: 1, name: 'CPU' },
{ id: 2, name: 'Memory' },
];
selectedProduct = null;
}
Page HTML:
<label>
Select product:<br/>
<select value.bind="selectedProduct">
<option model.bind="null">Choose...</option>
<option repeat.for="product of products"
model.bind="product">
${product.id} - ${product.name}
</option>
</select>
</label>
<div if.bind="selectedProduct">
Selected product 1: ${selectedProduct.id} - ${selectedProduct.name}
<div if.bind="selectedProduct.id > 0">
Selected product 2: ${selectedProduct.id} - ${selectedProduct.name}
</div>
</div>
When selecting CPU, then selecting null value, then selecting Memory, Selected product 1 is updated correctly with a value from a select element, but Selected product 2 is stuck with a CPU value.
How to bind selected value correctly inside the inner div?
In my application, I want to be able to display a content of selected item. Depending on an item type, I have a several <div if.bind="item.type === N">...</div> elements in order to display different HTML for each type of an item.
Note: binding doesn't work with newest packages, but works fine when I assign specific versions to the following packages in my package.json:
"aurelia-templating": "1.4.2"
"aurelia-templating-binding": "1.3.0"
"aurelia-templating-resources": "1.4.0"
"aurelia-templating-router": "1.1.0"