Refresh v-model - vue.js

I'm developing question paper application.
Once I type a question and hit the "+" button, the question goes to the question paper array and counter increased by one.
The problem is after I hit the "+" button, then also the question which I have entered previously is still in the fields of the UI. Because of I use v-model to bind the data fields.
What I want is a method to clear those previous question data in UI.
This is something similar to reset button function.
<template>
<div>
<div class="container" v-if="counter<=5">
<h2>Question {{counter}}</h2><hr>
<textarea rows="7" cols="75" v-model="question"></textarea><br><br>
1. Answer <input type="text" v-model="answer1"> <input type="radio" name="q1answer" value="1" v-model="correctAnswer"><br><br>
2. Answer <input type="text" v-model="answer2"> <input type="radio" name="q1answer" value="2" v-model="correctAnswer"><br><br>
3. Answer <input type="text" v-model="answer3"> <input type="radio" name="q1answer" value="3" v-model="correctAnswer"><br><br>
4. Answer <input type="text" v-model="answer4"> <input type="radio" name="q1answer" value="4" v-model="correctAnswer"><br>
<hr>
Knowledge Area <select v-model="knowledgeArea">
<option value="Maths">Mathematics</option>
<option value="Language">Language Skills</option>
<option value="gk">General Knowledge</option>
<option value="other">Other</option>
</select><br><br>
<button type="button" class="btn" #click="pushToArray" >
<span class="glyphicon glyphicon-plus"></span></button>
</div>
<div v-if="counter>5">
<button type="button" class="btn btn-primary" #click="onSubmit">Save Question Paper</button>
</div>
</div>
</template>
<script>
import axios from 'axios';
var questionPaper = [];
export default {
data () {
return {
question:'',
answer1:'',
answer2:'',
answer3:'',
answer4:'',
correctAnswer:'',
knowledgeArea:'',
counter:1,
show:true
}
},
methods: {
onSubmit () {
},
pushToArray(){
const formData = {
question: this.question,
correctAnswer: this.correctAnswer,
answer1: this.answer1,
answer2: this.answer2,
answer3: this.answer3,
answer4: this.answer4,
knowledgeArea:this.knowledgeArea
}
this.counter++;
questionPaper.push(formData);
}
}
}
</script>

Create a template data variable to use as a reset. For example
const templateData = {
question:'',
answer1:'',
answer2:'',
answer3:'',
answer4:'',
correctAnswer:'',
knowledgeArea:''
}
export default { // ...
use that to set your initial data
data() {
return {
counter: 1,
show: true,
...templateData
}
}
Now you can easily reset your data in the pushToArray method, eg
questionPaper.push(formData);
Object.assign(this, templateData);

Related

Vue.js adding a toggle and method to a button

I have a button that should toggle and also call a method. How do I achieve this? Seems like it can be only one or the other.
new Vue({
el: "#app",
data: {
iExist:false,
iDoNotExist: true,
},
methods: {
iSignedUpforThis: function(){
console.log("step X");
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p v-show="iExist"> i EXISTS </p>
<p v-show="iDoNotExist">
<strong> You are not found: </strong>
<form >
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
</form>
<BUTTON v-on:click="iExists = iDoNotExist">
TOGGLE MY EXISTENCE
</BUTTON>
</div>
Move
iExists = iDoNotExist to a method:
methods: {
iSignedUpforThis: function(){
this.iExist = this.iDoNotExist
console.log("step X");
}
}
<button v-on:click="iSignedUpForThis">
TOGGLE MY EXISTENCE
</button>
First off to accomplish your desired result you need only one Boolean variable. Then in your method just switch between true and false. Also you have an invalid markup - there is closing tap p but no closing. That's why your example does not work.
Notice: it's bad idea to nest form tag inside p tag, so use div instead. It's considered a good practice to associate your input with it's label using label tag. Also there is shortcut for v-on:click - #click. data should be an function that returns an object, this will prevent . multiple instance to share the same object.
If you follow above recommendations you will make your code much clear and bug-less.
new Vue({
el: '#app',
data: {
isExist: false,
},
methods: {
method() {
this.isExist = !this.isExist
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-show="isExist">I exist</div>
<div v-show="!isExist">
<strong>You are not found:</strong>
<form>
<label>First name:<br>
<input type="text" name="firstname" value="Mickey">
</label>
<br>
<label>Last name:<br>
<input type="text" name="lastname" value="Mouse">
</label>
</form>
</div>
<button #click="method">Toggle</button>
</div>
It might be late but I am sure it will help others. Create a component ToggleButton.js and paste the below codes.
<template>
<label for="toggle_button">
<span v-if="isActive" class="toggle__label">On</span>
<span v-if="! isActive" class="toggle__label">Off</span>
<input type="checkbox" id="toggle_button" v-model="checkedValue">
<span class="toggle__switch"></span>
</label>
</template>
<script>
export default {
data() {
return {
currentState: false
}
},
computed: {
isActive() {
return this.currentState;
},
checkedValue: {
get() {
return this.defaultState
},
set(newValue) {
this.currentState = newValue;
}
}
}
}
</script>
Take a look at the article to learn more https://webomnizz.com/create-toggle-switch-button-with-vue-js/

Vue JS insert and remove html elements dynamicaly

I want some thing like this,
If I hit "Add Another" button another set of input boxes should render below this set and this set's "Add Another" button should change to the "Remove This School" and the maximum number of input rows should limited to the 5.
I hope you understand my requirement.What I want is that the user can enter 5 schools or less than 5 schools.If he accidentally add some wrong information he should have a remove button to remove that record.How do I achieve this using Vue JS.
This is my code.
<template>
<div id="app">
<p>Please enter the schools you attained (Maximum five)</p>
School Name : <input type="text" name="" value="">
Location : <input type="text" name="" value="">
<button type="button" name="button" #click="addAnotherInputBox">Add Another</button>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
counter:0
}
},
methods:{
addAnotherInputBox(){
}
}
}
</script>
Here you go, although you should have filled the logic of your add button, but you can do that by your own
Here is a working fiddle: https://jsfiddle.net/Sletheren/Lo7t0myL/
<template>
<div id="app">
<p>Please enter the schools you attained (Maximum five)</p>
School Name : <input v-model="name" type="text" name="" value="">
Location : <input v-model="location" type="text" name="" value="">
<button type="button" name="button" #click="addAnotherInputBox">Add Another</button>
<ul class="schools">
<li v-for="school in schools">
{{school.name}} <button #click="removeSchool(school)">remove</button>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
counter:0,
name: '',
location:'',
schools: []
}
},
methods:{
addAnotherInputBox(){
// your logic here...
if(this.counter>4){
alert('you should delete one first! only 5 allowed')
}else{
const school = {
name: this.name, //name here
location: this.location //location here
}
this.counter++;
this.schools.push(school)
this.name='';
this.location=''
}
},
removeSchool(school) {
this.schools.splice(this.schools.indexOf(school),1);
this.counter--;
}
}
}
</script>

Angular2: How to enable save button if any model value changed on edit page

I am new for angular 2. I have a page where we can edit details of customer profile. How to enable save button if any property of has been changed. I know it is possible in angular1 by using $watch.
It is simple. dirty check your form if you are using #angular/forms.
create form
export class HeroDetailComponent4 {
heroForm: FormGroup;
states = states;
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.heroForm = this.fb.group({
name: ['', Validators.required ],
street: '',
city: '',
state: '',
zip: '',
power: '',
sidekick: ''
});
}
}
HTML:
<h2>Hero Detail</h2>
<h3><i>A FormGroup with multiple FormControls</i></h3>
<form [formGroup]="heroForm" novalidate>
<button (click)="submit()" [disabled]="!heroForm.dirty" type="button">Submit</button>
<div class="form-group">
<label class="center-block">Name:
<input class="form-control" formControlName="name">
</label>
</div>
<div class="form-group">
<label class="center-block">Street:
<input class="form-control" formControlName="street">
</label>
</div>
<div class="form-group">
<label class="center-block">City:
<input class="form-control" formControlName="city">
</label>
</div>
<div class="form-group">
<label class="center-block">State:
<select class="form-control" formControlName="state">
<option *ngFor="let state of states" [value]="state">{{state}}</option>
</select>
</label>
</div>
<div class="form-group">
<label class="center-block">Zip Code:
<input class="form-control" formControlName="zip">
</label>
</div>
<div class="form-group radio">
<h4>Super power:</h4>
<label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
<label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
<label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
</div>
<div class="checkbox">
<label class="center-block">
<input type="checkbox" formControlName="sidekick">I have a sidekick.
</label>
</div>
</form>
use heroForm.dirty to check whether form data is changed. it will set to true if any control inside heroForm has been changed.
<button (click)="submit()" [disabled]="!heroForm.dirty" type="button">Submit</button>
Refer angular docs for more info
you can use form control validation for it.
some thing like this in html template:
<form fxLayout="column" [formGroup]="form">
<mat-form-field class="mb-1">
<input matInput [(ngModel)]="userProfileChangeModel.firstName" placeholder="نام"
[formControl]="form1.controls['fname']">
<small *ngIf="form1.controls['fname'].hasError('required') && form1.controls['fname'].touched"
class="mat-text-warn">لطفا نام را وارد نمایید.
</small>
<small *ngIf="form1.controls['fname'].hasError('minlength') && form1.controls['fname'].touched"
class="mat-text-warn">نام باید حداقل 2 کاراکتر باشد.
</small>
<small *ngIf="form1.controls['fname'].hasError('pattern') && form1.controls['fname'].touched"
class="mat-text-warn">لطفا از حروف فارسی استفاده نمائید.
</small>
</mat-form-field>
<mat-card-actions>
<button mat-raised-button (click)="editUser()" color="primary" [disabled]="!form1.valid" type="submit">
ذخیره
</button>
</mat-card-actions>
</form>
and like this in ts file:
this.form = this.bf.group({
fname: [null, Validators.compose([
Validators.required,
Validators.minLength(2),
Validators.maxLength(20),
Validators.pattern('^[\u0600-\u06FF, \u0590-\u05FF]*$')])],
});
if:
[disabled]="!form1.valid"
is valid save button will be active
bast regards.
You can use disabled option like below :
<button [disabled]="isInvalid()" type="button" (click) = "searchClick()" class="button is-info">
<span class="icon is-small">
<i class="fa fa-search" aria-hidden="true"></i>
</span>
<span>Search</span>
</button>
you can create isInvalid() in your ts file and check if that property is empty or not and return that boolean value
and for hide button on a state you can use *ngIf in line directive.
This worked for me, pls try.
In your html,
<input type="text" [ngModel]="name" (ngModelChange)="changeVal()" >
<input type="text" [ngModel]="address" (ngModelChange)="changeVal()" >
<input type="text" [ngModel]="postcode" (ngModelChange)="changeVal()" >
<button [disabled]="noChangeYet" (click)="clicked()" >
<span>SUBMIT</span>
</button>
In your component
export class customer implements OnInit {
name: string;
address: string;
postcode: string;
noChangeYet:boolean = true;
constructor() {}
changeVal(){ // triggers on change of any field(s)
this.noChangeYet = false;
}
clicked(){
// your function data after click (if any)
}
}
Hope this is what you need.
Finally I resolved this issue.
import { Component, Input, Output, OnInit, AfterViewInit, EventEmitter, ViewChild } from '#angular/core';
#Component({
selector: 'subscribe-modification',
templateUrl: './subscribe.component.html'
})
export class SampleModifyComponent implements OnInit, AfterViewInit {
disableSaveSampleButton: boolean = true;
#ViewChild('sampleModifyForm') sampleForm;
ngAfterViewInit() {
setTimeout(() => {
this.sampleForm.control.valueChanges.subscribe(values => this.enableSaveSampleButton());
}, 1000);
}
enableSaveSampleButton() {
console.log('change');
this.disableSaveSampleButton = false;
}
}
HTML
<button id="btnSave" class="btn btn-primary" (click)="save()" />

vue js get multiple values from inputs

So I have 2 blocks of HTML, each containing 2 input fields and when submitting the form, I want to get all values from the inputs, and then create an object from the values...
As of know I've done it with plain vanilla JS and it works as it should, however if feels like to touching the DOM a bit to much, and also are very much depending on a specific DOM struckture, and therefore I was thinking there must be a better way, the VUE way so to speak, however im a bit stuck on how to do this the VUE way, which is why posting the question here in hope of getting some useful tips :)
HTML:
<form novalidate autocomplete="off">
<div class="input-block-container">
<div class="input-block">
<input type="text" placeholder="Insert name" name="name[]" />
<input-effects></input-effects>
</div>
<div class="input-block">
<input type="email" placeholder="Insert email address" name="email[]" />
<input-effects></input-effects>
</div>
</div>
<div class="input-block-container">
<div class="input-block">
<input type="text" placeholder="Insert name" name="name[]" />
<input-effects></input-effects>
</div>
<div class="input-block">
<input type="email" placeholder="Insert email address" name="email[]" />
<input-effects></input-effects>
</div>
</div>
<button class="button button--primary" #click.prevent="sendInvites"><span>Send</span></button>
</form>
JS:
methods: {
createDataObject() {
let emailValues = document.querySelectorAll('input[type="email"]');
emailValues.forEach((email) => {
let name = email.parentNode.parentNode.querySelector('input[type="text"]').value;
if(email.value !== "" && name !== "") {
this.dataObj.push({
email: email.value,
name
});
}
});
return JSON.stringify(this.dataObj);
},
sendInvites() {
const objectToSend = this.createDataObject();
console.log(objectToSend);
//TODO: Methods to send data to server
}
}
You can provide data properties for each of your inputs if you have static content.
data: function() {
return {
name1: '',
email1: '',
name2: '',
email2: ''
}
}
Then use them in your template:
<input type="text" placeholder="Insert name" v-model="name1" />
Access in method by this.name1
Try this
<div id="app">
<h1> Finds </h1>
<div v-for="find in finds">
<input name="name[]" v-model="find.name">
<input name="email[]" v-model="find.email">
</div>
<button #click="addFind">
New Find
</button>
<pre>{{ $data | json }}</pre>
</div>
Vue Component
new Vue({
el: '#app',
data: {
finds: []
},
methods: {
addFind: function () {
this.finds.push({ name: '', email: '' });
}
enter code here
}
});

vuejs set a radio button checked if statement is true

I am trying to make a radio button checked using vuejs v-for only if my if-statement is true. Is there a way to use vuejs' v-if/v-else for this type of problem?
in php and html I can achieve this by doing the following:
<input type="radio" <? if(portal.id == currentPortalId) ? 'checked="checked"' : ''?>>
Below is what I have so far using vuejs:
<div v-for="portal in portals">
<input type="radio" id="{{portal.id}}" name="portalSelect"
v-bind:value="{id: portal.id, name: portal.name}"
v-model="newPortalSelect"
v-on:change="showSellers"
v-if="{{portal.id == currentPortalId}}"
checked="checked">
<label for="{{portal.id}}">{{portal.name}}</label>
</div>
I know the v-if statement here is for checking whether to show or hide the input.
Any help would be very much appreciated.
You could bind the checked attribute like this:
<div v-for="portal in portals">
<input type="radio"
id="{{portal.id}}"
name="portalSelect"
v-bind:value="{id: portal.id, name: portal.name}"
v-model="newPortalSelect"
v-on:change="showSellers"
:checked="portal.id == currentPortalId">
<label for="{{portal.id}}">{{portal.name}}</label>
</div>
Simple example: https://jsfiddle.net/b4k6tpj9/
Maybe someone finds this approach helpful:
In template I assign each radio button a value:
<input type="radio" value="1" v-model.number="someProperty">
<input type="radio" value="2" v-model.number="someProperty">
Then in the component I set the value, i.e:
data: function () {
return {
someProperty: 2
}
}
And in this case vue will select the second radio button.
You can follow below option if you can adjust with your logic:
<div class="combination-quantity">
<input type="radio" value="Lost"
v-model="missing_status">
<label for="lost">Lost</label>
<br>
<input type="radio" value="Return Supplier" v-model="missing_status">
<label for="return_supplier">Return Supplier</label>
</div>
Value for missing_status could be "Lost" or "Return Supplier" and based on the value radio option will be get selected automatically.
Below is an example of keeping track of the selected radiobutton, by
applying a value binding to the object (:value="portal") and
applying a v-model binding to the currently selected object (v-model="currentPortal").
The radiobutton will be checked automatically by Vue, when the two match (no :checked binding necessary!).
Vue 3 with composition API
Vue.createApp({
setup() {
const portals = [{
id: 1,
name: "Portal 1"
}, {
id: 2,
name: "Portal 2"
}];
const currentPortal = portals[1];
return {
portals,
currentPortal
}
}
}).mount("#app");
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<template v-for="portal in portals">
<input
type="radio"
:id="portal.id"
name="portalSelect"
:value="portal"
v-model="currentPortal">
<label :for="portal.id">{{portal.name}}</label>
</template>
</div>
I would like to point out a few options when dealing with radios and vue.js. In general if you need to dynamically bind an attribute value you can use the shorthand binding syntax to bind to and calculate that value. You can bind to data, a computed value or a method and a combination of all three.
new Vue({
el: '#demo',
data() {
return {
checkedData: false,
checkedGroupVModel: "radioVModel3", //some defaul
toggleChecked: false,
recalculateComputed: null
};
},
computed: {
amIChecked() {
let isEven = false;
if (this.recalculateComputed) {
let timeMills = new Date().getMilliseconds();
isEven = timeMills % 2 === 0;
}
return isEven;
}
},
methods: {
onToggle() {
this.toggleChecked = !this.toggleChecked;
return this.toggleChecked;
},
mutateComputedDependentData() {
this.recalculateComputed = {};
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="demo">
<div>
<div>
<span>Simple Radio Group - Only one checked at a time. Bound to data.checkedData</span><br>
<label>Radio 1 - inverse of checkedData = {{!checkedData}}
<input type="radio" name="group1" value="radio1" :checked="!checkedData">
</label><br>
<label>Radio 2 - checkedData = {{checkedData}}
<input type="radio" name="group1" value="radio2" :checked="checkedData">
</label><br>
<span>Understanding checked attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-checked</span>
</div>
<br>
<div>
<span>Simple Radio - Checked bouned to semi-random computed object</span><br>
<label>Radio 1: {{amIChecked}}
<input type="radio" :checked="amIChecked">
</label>
<label>Recalculate Computed Value
<button type="button" #click="mutateComputedDependentData">Click Me Several Times</button>
</label>
</div>
<br>
<div>
<span>Simple Radio Group - v-model bound value = {{checkedGroupVModel}}</span><br>
<label>Simple Radio 1:
<input type="radio" name="vModelGroup" value="radioVModel1" v-model="checkedGroupVModel">
</label><br>
<label>Simple Radio 2:
<input type="radio" name="vModelGroup" value="radioVModel2" v-model="checkedGroupVModel">
</label><br>
<label>Simple Radio 3:
<input type="radio" name="vModelGroup" value="radioVModel3" v-model="checkedGroupVModel">
</label>
</div>
<br>
<div>
<span>Simpe Radio - click handler to toggle data bound to :checked to toggle selection</span><br>
<label>Toggle Radio = {{toggleChecked}}
<input type="radio" :checked="toggleChecked" #click='onToggle()'>
</label>
</div>
</div>
</div>