I'm trying to set the value of an input corresponding to the selected radio button, but I just can't figure out how.
<input type="text" class="input" name="provider" v-model="selected_provider">
<b-radio-group v-model="provider_options">
<div class="field">
<template v-for="provider in providers">
<b-radio
name="select_provider[]" id="provider_#{{ $index }}"
model="selected_provider"
value="provider"
type="radio">
#{{ provider.provider_name }}
</b-radio>
</template>
</div>
</b-radio-group>
I've managed to get an array to display and that the input shows whatever is written in selected_provider, but I just don't know how to link those together.
var app = new Vue({
el: '#app',
data: {
selected_provider: '',
providers: [
{
provider_name: 'Twitch',
provider_url: 'https://www.twitch.tv/'
},
{
provider_name: 'Smashcast',
provider_url: 'https://www.smashcast.tv/'
},
{
provider_name: 'AzubuFrost',
provider_url: 'https://www.smashcast.tv/'
}
]
},
});
furthermore I'd like to attach the value of
<input type="text" class="input" name="name" id="name">
to the end of provider_url in selected_provider
Is someone so kind to help me?
If you set your for-loop to v-for="(provider, index) in providers"You can put a v-on:click="setSelectedProvider(index)" inside <b-radio></b-radio> and can create a method that looks like this:
setSelectedProvider: function(index){
this.$set(this, 'selected_provider', index);
}
Whenever a radio button is clicked this will set selected_provider to the index of the clicked radio button.
As for attaching the value of your other input to the end of provider_url, you can create a method that does this:
updateProviderURL: function(event){
this.$set(this.providers[this.selected_provider], 'provider_url',
'https://www.twitch.tv/' + event.currentTarget.value);
}
You can then add a listener to your input that looks like this:
v-on:input="updateProviderURL($event)"
It's good to set selected_provider by default to 0 inside the data part of your component so that the updateProviderURL function never tries to set a part of the array that doesn't exist ;)
Related
In each set of group I wants to select one radio input by default.
each menu have multiple items. user need to select one item from each menu. so, I'm trying to select one item by default. How can I do that?
<div v-for="menu in menus">
<h4>#{{ menu.name }}</h4>
<div v-for="item in menu.menuitems">
<input type="radio" v-model="selected_items[menu.id]" :value="item" :key="item.item_id"> #{{ item.name }}
</div>
</div>
Firstly, you need to set a name attribute to the radio buttons in each menu, so that only one can be selected at a time.
And to set the first item of each menu as selected, you can use v-for index like:
<div v-for="item in menu.menuitems">
<input type="radio" v-model="selected_items[menu.id]"
:value="item.id"
:name="menu.id"
:key="item.item_id"> #{{ item.name }}
</div>
You will also need to update radio button :value from items to item.item_id and also modify :key="items.item_id" to :key="item.item_id". I think this was typo, as no variable exists in this scope like items.
and then inside mounted vue instance or any initial function inside methods you can set the values for each group item like:
mounted: function() {
this.menus.forEach(function(menu) {
this.selected_items[menu.id] = this.menu.menuitems.length ? this.menu.menuitems[0].id : null;
})
}
assuming menuitems[0] in an object with properties like item_id & name
You can still get selected item for each menu like:
this.menus.forEach(function(menu) {
var selectedItem = this.menu.menuitems.find(m => m.id == this.selected_items[menu.id]);
console.log(selectedItem)
// Retursn { id: xxx, name: 'xxx' }
})
//this is my html code where i have a datepicker component wheer i want to throw a validation but i want the error message to be shown once the user leaves this feild and go on some other inputfeild of the form
<datepicker v-model="present_complaint.experienceSince"
name="date" placeholder=24-july-1994>
</datepicker>
<span class="error-msg" v-show="present_complaint.experienceSince ==''">
Date is a mandatory field
</span>
//this is my js code
present_complaint:{
description:'',
}
//currently when the page loads by default the error message is there on the datepicker as by default it is empty now i want that it should only be diaplayed when user clicks on it and leave it not selecting any date basically when it goes to any other feild and not selecting any date
I have a solution for you.
<div id="app">
<input type="text" placeholder="type something" v-model.trim="text" #blur="blur">
<span v-show="text === ''">Please Fill the input</span>
</div>
new Vue({
el: "#app",
data: {
text: null
},
methods: {
blur() {
if(this.text === null) {
this.text = ''
}
}
}
})
The answer it is simplified to understand the logic.Once you do,you can solve your problem by replacing some code.Take a look to the demo
I'm working with a template form component with angular2 and I cannot get to set the focus in my firstName input element after submit the form. The form is reseted fine but no way of setting focus.
This is my component code:
export class TemplateFormComponent {
#ViewChild('f') form: any;
onSubmit() {
if (this.form.valid) {
console.log("Form Submitted!");
this.form.reset();
this.form.controls.firstName.focus();
}
}
}
and my template code:
<form novalidate autocomplete="off" #f="ngForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label>First Name</label>
<input type="text"
class="form-control"
name="firstName"
[(ngModel)]="model.firstName"
required
#firstName="ngModel">
</div>
</form>
On your view, set a reference to the input field you want to focus (you already have that with #firstName).
Then, on your component code, create an access to it with #ViewChild:
#ViewChild('firstName') firstNameRef: ElementRef;
And finally, right after reseting the form:
this.firstNameRef.nativeElement.focus()
ps.: I would expect the FormControl api to expose a focus method, but this issue on gitHub suggests it may never happen.
For a more generic solution see
Is it possible to get native element for formControl?
`
#Directive({
selector: '[ngModel]',
})
export class NativeElementInjectorDirective {
constructor(private el: ElementRef, private control : NgControl) {
(<any>control.control).nativeElement = el.nativeElement;
}
}
`
This will add the nativeElement to EACH form control once you add the directive to your module.
UPDATE: a much simpler solution for this usecase
To set focus on the first invalid element on a form create a directive like this:
import { Directive, HostListener, ElementRef} from '#angular/core';
#Directive({
selector: '[focusFirstInvalidField]'
})
export class FocusFirstInvalidFieldDirective {
constructor(private el: ElementRef) { }
#HostListener('submit')
onFormSubmit() {
const invalidElements = this.el.nativeElement.querySelectorAll('.ng-invalid');
if (invalidElements.length > 0) {
invalidElements[0].focus();
}
}
}
Then simply add it to your form element tag
Simple solution: add "autofocus" to your input element properties.
<input type="text" class="form-control" name="firstName" autofocus required>
I have controller as follows:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.questionTypes = [
{display: 'Text', 'name': 'text'},
{display: 'Paragraph', 'name': 'textarea'},
{display: 'Multiple Choice', 'name': 'radio'},
];
$scope.top = {
heading: '',
questions: [
{
tite: 'title 1',
choices: ['']
}
]
};
});
And an HTML body as follows:
<body ng-controller="MainCtrl">
<input ng-model="top.heading" placeholder="heading"/>
<br/>
<div ng-repeat="question in top.questions track by $index">
<select ng-model="question.type" ng-options="c.name as c.display for c in questionTypes"></select>
<div ng-if="question.type == 'radio'">
<div ng-repeat="option in question.choices track by $index">
<input type="text" ng-model="option"/>
<button ng-click="question.choices.push('')" ng-disabled="$index < question.choices.length - 1">Add</button>
<button ng-click="question.choices.splice($index, 1)" ng-disabled="question.choices.length == 1">Del</button>
</div>
</div>
</div>
<pre>{{top | json}}</pre>
</body>
When the user makes the Multiple Choice selection, I want to show a fragment that provides the ability to add various choices. The choices are displayed in repeater.
That all works, but data binding on nested repeater is not working. I assuming this has something to do with scoping, but I can't figure it out.
Any help would be appreciated.
I have created a plunkr at http://plnkr.co/edit/6FxY44HgddRjrLOHlQGF
After fumbling around with this for a while, this is what I did to fix the problem.
I changed:
<input type="text" ng-model="option"/> //after changing model to ng-model
To
<input type="text" ng-model="question.choices[$index]"/>
This allowed the input to reference the parent question object and the choices array on the object instead of referencing the option reference within ng-repeat.
I have a directive that sets a CSS class on a form element based on its $valid value. I want to use it with a radio button list. There a multiple radio buttons in the set but I only need to add the directive to one of them because a) they all control the same model and b) the CSS ultimately will reveal a single image tag which I only want once per radio button list.
Here's some HTML:
<div ng-app="myApp">
<input required type="radio" ng-model="type" name="typeGroup" value="type1">Type 1
<input add-validation-class required type="radio" ng-model="type" name="typeGroup" value="type2">Type 2
</div>
Script:
angular.module('myApp', []).directive('addValidationClass', function() {
return {
require: '^ngModel',
link: function($scope, $element, $attrs, $ngModel) {
if (!$ngModel) return;
var update = function () {
alert($ngModel.$dirty);
$element
.removeClass()
.addClass($ngModel.$dirty ? ($ngModel.$valid ? 'valid' : '') : '');
};
$scope.$watch($attrs.ngModel, function (newValue, oldValue) {
update();
});
}
};
});
Fiddle: http://jsfiddle.net/JqBgs/
You can see from the fiddle that the watch fires update regardless of the radio button clicked on. This is what I expected because both radio buttons control the same model. However you can also see that the left radio button isn't dirty. So the CSS class isn't applied.
Why isn't it dirty?
I put this in the HTML:
<div ng-app="myApp">
<input ng-change="myForm.validateRadio.$dirty = true" required type="radio" ng-model="type" name="typeGroup" value="type1">Type 1
<input name="validateRadio" add-validation-class required type="radio" ng-model="type" name="typeGroup" value="type2">Type 2
</div>
What a ridiculous bug in Angular.