I need to show different components depending on the selected option. I don’t know how to write the code for showing component one or two. Are there any examples available?
<template>
<div class="col-md-3 md-form mr-2">
<i class="fa fa-envelope prefix grey-text"></i>
<label class="font-weight-light mb-2">Component</label>
<select v-model="comp" class="form-control">
<option value="">Select your component to show</option>
<option value="">Show component 1</option>
<option value="SentenceSelected">Show component 2</option>
</select>
</div>
</template>
import SuspensionSelected from '../precautonary/mix/SuspensionSelected'
import SentenceSelected from '../precautonary/mix/SentenceSelected'
export default {
name: "PrecautionCreate",
components: {
SuspensionSelected,
SentenceSelected
},
data: () => ({
selectedyear: '',
selectedcause:'',
comp: ''
})
};
enter image description here
You can use a dynamic component:
<component :is="comp"></component>
Demo:
SuspensionSelected = {
template: `<div>Suspension Component</div>`
}
SentenceSelected = {
template: `<div>Sentence Component</div>`
}
new Vue({
el: "#app",
name: "PrecautionCreate",
components: {
SuspensionSelected,
SentenceSelected
},
data: () => ({
selectedyear: '',
selectedcause:'',
comp: ''
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<i class="fa fa-envelope prefix grey-text"></i>
<label class="font-weight-light mb-2">Component</label>
<select v-model="comp" class="form-control">
<option value="">Select your component to show</option>
<option value="SuspensionSelected">Suspension</option>
<option value="SentenceSelected">Sentence</option>
</select>
<component :is="comp"></component>
</div>
Related
I have two select and I show value if they exist:
page.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
customer: any = {
city: '',
state: '',
};
ngOnInit() {
// I recover this info from BE
this.customer.state = 'England';
this.customer.city = 'London';
}
}
page.html
<div class="col configurator-form-input col-12 col-md-6">
<label class="text">State *</label>
<div
class="input-group input-error"
[ngClass]="
customer.state ? 'input-group input error' : 'input-group input-error'
"
>
<select
id="state"
class="form-control"
[(ngModel)]="customer.state"
[ngModelOptions]="{ standalone: true }"
(change)="onChangeProvinceForState($event.target.value)"
appTab
tabIndex="14"
>
<option disabled value="">Select State</option>
<option
*ngFor="let state of stateList"
ngDefaultControl
[value]="state.name"
>
{{ state.name }}
</option>
</select>
</div>
</div>
<div class="col configurator-form-input">
<label class="text">City *</label>
{{ this.customer.city }}
<div
class="input-group input-error"
[ngClass]="customer.city ? 'input-group' : 'input-group input-error'"
>
<!-- <span class="fake-option" *ngIf="existingCustomer">{{customer.city}}</span> -->
<select
id="city"
name="city"
class="form-control"
[(ngModel)]="customer.city"
[ngModelOptions]="{ standalone: true }"
appTab
tabIndex="15"
>
<option value="">Select City</option>
<option *ngFor="let city of citiesList" ngDefaultControl [value]="city">
{{ city }}
</option>
</select>
</div>
</div>
https://stackblitz.com/edit/angular-wyendp?file=src/app/app.component.html
I recover the city and state from an api call, but I don't understand how to show in the select directly
EDIT:
onChangeStateForCity(e) {
console.log("e ", e)
let countiesObservable = this.citiesService.getAllState();
countiesObservable.pipe(untilDestroyed(this)).subscribe((data: any) => {
this.citiesList = data[e];
});
}
You are missing the declaration of properties stateList and citiesList. I have modified your SB, to generate some static dropdown down options. You can easily assign these variables to the response you get from your API.
Stackblitz demo
app.component.ts (defined the variables):
stateList = [
'England',
'France'
]
citiesList = [
'London',
'Paris'
]
app.component.html (bind them in template):
<option *ngFor="let state of stateList" ngDefaultControl [value]="state">
<option *ngFor="let city of citiesList" ngDefaultControl [value]="city">
Just add array of stateList and citiesList.
stateList = [{ name: 'England' }];
citiesList = ['London'];
I have 2 dropdown menus, the second one changes values depending on the selection of the first dropdown.
All I want to do is set the first value of the second dropdown to be selected by default no matter what the option in the first dropdown is.
At the moment, the default selection of the second dropdown is always empty.
I tried fetching the values from types and loading them via v-for on the option tag and setting :selected="index===0" but it didn't work either.
Demo: https://codesandbox.io/s/relaxed-flower-2hjox1?file=/src/App.vue
The Template
<div class="col-md-6">
<label for="type" class="form-label">Type</label>
<select id="type" class="form-select" v-model="form.type">
<option value="en-US" selected>English (US)</option>
<option value="en-GB">English (British)</option>
</select>
</div>
<div class="col-md-6">
<label for="selected" class="form-label">Option 2</label>
<div v-if="form.type === 'en-GB'">
<select id="selected" name="selected" class="form-select" v-model="form.selected">
<option value="Arsenal">Arsenal</option>
<option value="Chelsea">Chelsea</option>
<option value="Liverpool">Liverpool</option>
</select>
</div>
<div v-else-if="form.type === 'en-US'">
<select id="selected" name="selected" class="form-select" v-model="form.selected">
<option value="Lakers">Lakers</option>
<option value="Bulls">Bulls</option>
<option value="Mavericks">Mavericks</option>
</select>
</div>
</div>
Javascript
export default {
name: "App",
data() {
return {
form: {
type: 'en-GB',
selected: ''
},
types: {
american: ['Lakers', 'Bulls', 'Mavericks'],
british: ['Arsenal', 'Liverpool', 'Chelsea']
}
}
},
};
const app = Vue.createApp({
data() {
return {
form: {
type: "en-GB",
selected: "",
},
types: {
american: ["Lakers", "Bulls", "Mavericks"],
british: ["Arsenal", "Liverpool", "Chelsea"],
},
};
},
watch: {
'form.type': {
handler() {
this.form.selected = this.form.type === "en-GB" ? this.types.british[0] : this.types.american[0]
},
immediate: true
}
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div class="col-md-6">
<label for="type" class="form-label">Type</label>
<select id="type" class="form-select" v-model="form.type">
<option value="en-US" selected>English (US)</option>
<option value="en-GB">English (British)</option>
</select>
</div>
<div class="col-md-6">
<label for="selected" class="form-label">Option 2</label>
<div v-if="form.type === 'en-GB'">
<select
id="selected"
name="selected"
class="form-select"
v-model="form.selected"
>
<option value="Arsenal">Arsenal</option>
<option value="Chelsea">Chelsea</option>
<option value="Liverpool">Liverpool</option>
</select>
</div>
<div v-else-if="form.type === 'en-US'">
<select
id="selected"
name="selected"
class="form-select"
v-model="form.selected"
>
<option value="Lakers">Lakers</option>
<option value="Bulls">Bulls</option>
<option value="Mavericks">Mavericks</option>
</select>
</div>
</div>
</div>
You can create watcher and set default values for second select:
watch: {
'form.type': {
handler() {
this.form.selected = this.form.type === "en-GB" ? this.types.british[0] : this.types.american[0]
},
immediate: true
}
}
All I want to do is set the first value of the second dropdown to be
selected by default no matter what the option in the first dropdown
is.
Add a watcher, which watches form.type, then pick the first item from types
Note, I've changed american key to the key your using for type, then you can loop over the options, if you don't have that in place you'll need mapping object anyway typeMap: {'en-US': 'american', 'en-GB': 'british' } ... types[typeMap[form.type]]
new Vue({
el: '#app',
data() {
return {
form: {
type: 'en-GB',
selected: ''
},
types: {
'en-US': ['Lakers', 'Bulls', 'Mavericks'],
'en-GB': ['Arsenal', 'Liverpool', 'Chelsea']
}
}
},
watch: {
'form.type' () {
this.form.selected = this.types[this.form.type][0]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="app">
<div class="col-md-6">
<label for="type" class="form-label">Type</label>
<select id="type" class="form-select" v-model="form.type">
<option value="en-US" selected>English (US)</option>
<option value="en-GB">English (British)</option>
</select>
</div>
<div class="col-md-6">
<label for="selected" class="form-label">Option 2</label>
<select id="selected" name="selected" class="form-select" v-model="form.selected">
<option v-for="name in types[form.type]">{{ name }}</option>
</select>
</div>
</div>
I am adding select fields using VueJS & it's working fine, but I want to add validation.
If the user selects 8mm in the first select then 8mm will disabled in other select tags.
Here is HTML & Vue JS code
<div class="form-group" v-for="(input,k) in inputs" :key="k">
<select v-model="input.thickness" name="thickness-`${k}`" class="basicRate block w-full p-3 mt-2 text-gray-700 bg-gray-200 appearance-none focus:outline-none focus:bg-gray-300 focus:shadow-inner" required>
<option disabled selected value> -- Select thickness -- </option>
<option value="8">8mm</option>
<option value="10">10mm</option>
<option value="12">12mm</option>
<option value="16">16mm</option>
<option value="20">20mm</option>
<option value="25">25mm</option>
</select>
<input type="text" class="form-control" v-model="input.qty">
<span>
<i class="fas fa-minus-circle" #click="remove(k)" v-show="k || ( !k && inputs.length > 1)"></i>
<i class="fas fa-plus-circle" #click="add(k)" v-show="k == inputs.length-1"></i>
</span>
</div>
var app = new Vue({
el: "#app",
data: {
inputs: [
{
thickness:'',
qty: ''
}
]
},
methods: {
add(index) {
this.inputs.push({ thickness: '', qty: '' });
},
remove(index) {
this.inputs.splice(index, 1);
}
}
});
As you see the first two drop-downs have the same value meaning the user can select the same values. I'm looking for simple validation where if the user selects some option then he or she won't select the same value in other dropdowns.
Thanks in advance.
You could use an array of each selects' value. Just update the array whenever the change event is fired and conditionally add the disabled attribute based on these values:
var app = new Vue({
el: "#app",
data: {
thicknesses: [],
inputs: [{
thickness: '',
qty: ''
},
{
thickness: '',
qty: ''
},
{
thickness: '',
qty: ''
},
{
thickness: '',
qty: ''
},
]
},
methods: {
handleChange(e) {
this.thicknesses = [...this.$refs.selects.children].map(select => {
return select.children[0].value;
})
},
add(index) {
this.inputs.push({
thickness: '',
qty: ''
});
},
remove(index) {
this.inputs.splice(index, 1);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" ref="selects">
<div class="form-group" v-for="(input,k) in inputs" :key="k">
<select v-model="input.thickness" name="thickness-`${k}`" required #input="handleChange($event)">
<option disabled selected value> -- Select thickness -- </option>
<option value="8" :disabled="thicknesses.includes('8')">8mm</option>
<option value="10" :disabled="thicknesses.includes('10')">10mm</option>
<option value="12" :disabled="thicknesses.includes('12')">12mm</option>
<option value="16" :disabled="thicknesses.includes('16')">16mm</option>
<option value="20" :disabled="thicknesses.includes('20')">20mm</option>
<option value="25" :disabled="thicknesses.includes('25')">25mm</option>
</select>
</div>
</div>
In my project I am using Angular 8.
Created method to bind user to project according to their id, tested with postman back end functionality works properly.
My service for bindUser method:
bindUserToProject(userId: number, projectId: number) {
const seperator = "/";
const body = { userId, seperator, projectId };
return this.http.post(this.baseUrl + '/bind/', body)
}
Component:
export class AddProjectForUserComponent implements OnInit {
users: any = {};
projects: any = {};
constructor(private router: Router, private projectService: ProjectService, private vmService:
VmService, private userService: UserService) { }
ngOnInit() {
this.users = this.getUsersForProject()
this.projects = this.getProjects()
}
getUsersForProject() {
this.projectService.getUsersForProject().subscribe(u => this.users = u);
}
getProjects() {
this.vmService.getProjectsForVm().subscribe(p => this.projects = p)
}
goBackToUserProjects() {
this.router.navigate(["/user-projects"])
}
bindUserToProject(userId: number, projectId: number) {
this.userService.bindUserToProject(userId, projectId);
}
HTML:
<div class="bindProject">
<form #bindProject="ngForm" (ngSubmit)="bindUserToProject()">
<h2 class="text-center text-primary">Bind User to Projects</h2>
<div class="input-group mt-1">
<div class="input-group-prepend">
<div class="input-group-text">
<i class="fas fa-dot-circle text-info"></i> Users
</div>
</div>
<select name="userId" [(ngModel)]="users.userId" class="form-control" required>
<option disabled>-Please choose User-</option>
<option *ngFor="let item of users" [ngValue]="item.userId">
{{ item.userName }}
</option>
</select>
</div>
<div class="input-group mt-1">
<div class="input-group-prepend">
<div class="input-group-text">
<i class="fas fa-dot-circle text-info"></i> Projects
</div>
</div>
<select name="projectId" [(ngModel)]="projects.projectId" class="form-control" required>
<option disabled>-Please choose Projects-</option>
<option *ngFor="let item of projects" [ngValue]="item.projectId">
{{ item.projectName }}
</option>
</select>
</div>
<div class="form-group mt-1">
<button [disabled]="!bindProject.valid" class="btn btn-success btn-sm mr-5" type="submit"><i
class="fas fa-plus"></i> Add</button>
<button (click)="goBackToUserProjects()" class="btn btn-sm btn-outline-success"><i
class="fas fa-tasks"></i> Go back to user projects</button>
</div>
</form>
</div>
Question is how can I get selected id from both dropdown and pass it to my bindToProject() method.
You should bind the select values with some variables say selectedProject and selectedUser.
app.component.ts :
selectedUser : number;
selectedProject : number;
bindUserToProject() {
this.userService.bindUserToProject(this.selectedUser, this.selectedProject);
}
app.component.html :
<select name="userId" [(ngModel)]="selectedUser">
<option disabled>-Please choose User-</option>
<option *ngFor="let item of users" [ngValue]="item.userId">
{{ item.userName }}
</option>
</select>
<select name="projectId" [(ngModel)]="selectedProject">
<option disabled>-Please choose Projects-</option>
<option *ngFor="let item of projects" [ngValue]="item.projectId">
{{ item.projectName }}
</option>
</select>
Demo : https://stackblitz.com/edit/angular-3udq1g
Define a variable in your component called something like selectedUserId, change [(ngModel)]="users.userId" to [(ngModel)]="selectedUserId". Then in bindUserToProject() you can access that value directly from the component.
You can do the same for the projects dropdown.
try like this
<form #bindProject="ngForm" (ngSubmit)="bindUserToProject(bindProject.value)">
<select name="userId" class="form-control" ngModel required>
<option disabled>-Please choose User-</option>
<option *ngFor="let item of users" [ngValue]="item.userId">
{{ item.userName }}
</option>
</select>
<select name="projectId" class="form-control" ngModel required>
<option disabled>-Please choose Projects-</option>
<option *ngFor="let item of projects" [ngValue]="item.projectId">
{{ item.projectName }}
</option>
</select>
<button type="submit">
Add
</button>
</form>
component
bindUserToProject({userId, projectId}) {
this.userService.bindUserToProject(userId, projectId);
}
bindUserToProject will get the hole form value but this {userId, projectId} is ES2015 feature called destruction
demo 🚀
In case someone has same issue my service also was wrong which threw exception json Parser.
I changed this one to and it worked fine:
bindUserToProject(userId: number, projectId: number) {
return this.http.post(this.baseUrl + '/bind/' + userId + "/" + projectId, {})
}
These are the following step of solution-:
Initialize two variable for userId and projectId.
Apply these variable in ngModel like [(ngModel)]="UserId" and [(ngModel)]="projectId"
use (ngSubmit)="bindUserToProject()"
In component file use initialized variables in bindUserToProject() function.
Select dropdown and click Submit.
Now, you have a selected value in your variable.
I have been following the vue js wrapper component example. I am trying to change how this works to allow me to add a v-select2 directive to a regular select box rather than have to create templates and components for each one.
I have a JS Bin here which shows using the component.
The component html is as follows (with the options being set in the JS).
<div id="app"></div>
<script type="text/x-template" id="demo-template">
<div>
<p>Selected: {{ selected }}</p>
<select2 :options="options" v-model="selected">
<option disabled value="0">Select one</option>
</select2>
<p>Selected: {{ selected2 }}</p>
<select2 :options="options" v-model="selected2">
<option disabled value="0">Select one</option>
</select2>
<p>Selected: {{ selected3 }}</p>
<select2 :options="options" v-model="selected3">
<option disabled value="0">Select one</option>
</select2>
</div>
</script>
<script type="text/x-template" id="select2-template">
<select>
<slot></slot>
</select>
</script>
With the JS as follows:
Vue.component('select2', {
props: ['options', 'value'],
template: '#select2-template',
mounted: function () {
var vm = this
$(this.$el)
.val(this.value)
// init select2
.select2({ data: this.options })
// emit event on change.
.on('change', function () {
vm.$emit('input', this.value)
})
},
watch: {
value: function (value) {
// update value
$(this.$el).val(value)
},
options: function (options) {
// update options
$(this.$el).select2({ data: options })
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
})
var vm = new Vue({
el: '#app',
template: '#demo-template',
data: {
selected: 0,
selected2: 0,
selected3: 0,
options: [
{ id: 1, text: 'Hello' },
{ id: 2, text: 'World' }
]
}
})
What I want is something like the following
<div id="app">
<p>Selected: {{ selected }}</p>
<select name="selected1" id="selected1" class="select2" v-selectize v-model="selected">
... options here ...
</select>
<p>Selected: {{ selected2 }}</p>
<select name="selected2" id="selected2" class="select2" v-selectize v-model="selected2">
... options here ...
</select>
<p>Selected: {{ selected3 }}</p>
<select name="selected3" id="selected3" class="select2" v-selectize v-model="selected3">
... options here ...
</select>
</div>
You can use your component in pretty much the way you want to use your directive:
<select2 name="selected1" id="selected1" v-model="selected">
<option disabled value="0">Select one</option>
<option value="1">Hello</option>
<option value="2">World</option>
</select2>
The name and id attributes get transferred to the underlying select element.
There is no (good) way to do this with a directive, which is an intentional design decision in Vue 2. There is no communication channel between a directive and the Vue as there is between a component and its parent component. A directive is not a sub-Vue, as a component is, it is a way of dealing with a small piece of the DOM in isolation.
I do not think there would be any particular advantage to writing this with a directive rather than a component.