How to clear input fields after adding a new element? - javascript

I have an array with the students.
I have the implementation of the addition of students.
Question: how to clean up after pressing the field? Fields must be cleaned so that when you try to enter new values ​​were not set to the old values.
Tried everything, nothing works. Neither the <form> -> <button type = "reset">, or the selectors ...
What can be done to solve this problem?
index.html
......
<!-- add new student -->
<br>
<input v-model="students.name" placeholder="surname">
<select v-model="students.group">
<option value="1">1</option>
<option value="2">2</option>
</select>
<input v-model="students.year" placeholder="Bitrh year">
<input type="checkbox" v-model="students.done">
<label>done</label>
<input v-model.number="students.mark" type="number" placeholder="mark">
<button type="reset" #click="addStudent()">add to array</button>
</div>
<!-- /add new student -->
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="/index.js"></script>
index.js
let students = [
{
id: '1',
name: "Test",
group: "1",
year: "1985",
done: true,
mark: 4,
},
]
var app = new Vue ({
el: '#app',
data: {
students: [],
search: '',
stud: students.slice(),
},
methods: {
deleteStudent(studId) {
this.stud = this.stud.filter(elem => {
return elem.id != studId;
});
},
addStudent() {
const id = this.stud.length + 1;
this.stud.push({ id, ...this.students });
}
}
})

I don't know vue, but you can always select all inputs and set it's value on '' :
document.querySelectorAll('input').forEach(input => input.value='')
in best case apply it to container so sth like that:
document.querySelector('.formClassName').querySelectorAll('input').forEach(input => input.value='')

Just use following:
deleteStudent(studId) {
this.stud.splice(students.id, 1)
}
You can splice something based on it's id the 1 after the comma is that it deletes 1 stud-data from your id.

When you want to use a v-model on your form and let the user enter some data, you should pass an initial object to your inputs. And when the user submits the form, you'll push that data to your array, following to reset your initial object.
So this implementation will help you:
<!-- add new student -->
<br>
<input v-model="initialState.name" placeholder="surname">
<select v-model="initialState.group">
<option value="1">1</option>
<option value="2">2</option>
</select>
<input v-model="initialState.year" placeholder="Bitrh year">
<input type="checkbox" v-model="initialState.done">
<label>done</label>
<input v-model.number="initialState.mark" type="number" placeholder="mark">
<button type="reset" #click="addStudent()">add to array</button>
</div>
<!-- /add new student -->
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="/index.js"></script>
var app = new Vue ({
el: '#app',
data: {
students: [],
initialState: {
id: '',
name: '',
group: '',
year: '',
done: true,
mark: 0
},
search: '',
},
methods: {
deleteStudent(studId) {
this.students = this.students.filter(elem => {
return elem.id != studId;
});
},
addStudent() {
const id = this.students.length + 1;
this.students.push({ id, this.initialState });
this.initialState = JSON.parse(JSON.stringify({
id: '',
name: '',
group: '',
year: '',
done: true,
mark: 0
}));
}
}
})

Related

How to implement "Select All" for vue-treeselect library?

There is a multi-select feature available in the vue-treeselect library; but what I am looking at is a "Select All" option (see snippet below):
Is there some undocumented config or can this feature be implemented without too much hassle?
add this code between the treeselect tag
<treeselect>
<div class="d-flex p-1 justify-content-center" **slot="before-list"**>
<button #click="selectAll()" type="button" class="btn btn-light">Select All</button>
<button #click="deselectAll()" type="button" class="btn btn-light">Deselect All</button>
</div>
</treeselect>
and in your method add these two functions
selectAll(){
this.ids= [];
this.options.forEach((value, index) => {
this.ids.push(value);
});
},
deselectAll(){
this.ids = null;
},
Yes, you can do it but for this, you have to make a custom code.
use the below code.
This is a TreeSelect option
<div class="form-group">
<span>Users</span>
<treeselect
v-model="api.user_ids"
:options="api.users.results"
:multiple="true"
#input="selectAll"
placeholder="Select Users"
/>
<br>
</div>
Vuejs code
var app = new Vue({
delimiters: ["[[", "]]"],
el: "#content",
data: {
api: {
users: {
results: [
{
id: 1,
label: "Demo"
},
{
id: 2,
label: "Test"
},
],
},
},
},
});
If you don't have any "Select All" option in "api.users.results" array then you have to add custom value at the zero(0) index.
var self = this;
var response = self.api.users.results;
var options = [{
id: "all",
label: 'Select All',
}]
self.api.users.results = options.concat(self.api.users.results);
self.$forceUpdate();
This is a method for selecting all options.
selectAll: function () {
var self = this;
// check 'all' value is available in user id's array
if (self.api.user_ids.includes('all')) {
self.api.user_ids = [];
_.forEach(self.api.users.results, function (item) {
if (item.id != 'all'){
// push each item id in user id's array
self.api.user_ids.push(item.id);
}
});
}
}

vue.js computed property not triggered

Vue JS computed property is not triggered With this markup
<!-- language: lang-html -->
<p>£{{plant_price}}</p>
<div v-if="selected.plant.variations.length > 0 ">
<select v-model="selected.plant.selected_variation" class="form-control">
<!-- inline object literal -->
<option v-for="(variation, i) in selected.plant.variations" :selected="variation.id == selected.plant.selected_variation ? 'selected' : ''":value="variation.id">
{{variation.name}}
</option>
</select>
</div>
<!-- language: lang-js -->
var app = new Vue({
el: '#vueApp',
data: {
selected: {
type: {a: '' , b: ''},
vehicle: '',
plant: {
}
},
computed: {
plant_price: function() {
if (this.selected.plant.variations.length > 0 ) {
var variant = _.find(this.selected.plant.variations, {id: this.selected.plant.selected_variation });
return variant.price;
} else {
return this.selected.plant.price;
}
}
...
selected.plant is populated by clicking on a plant - triggering the updateSelected method.
<div class="col-sm-4" v-for="(plant, i) in step2.plants">
<div v-on:click="updateSelected(plant)" ....
methods: {
updateSelected: function(plant) {
this.selected.plant = plant; // selected plant
if (this.selected.plant.variations.length > 0 ) {
this.selected.plant.selected_variation = this.selected.plant.variations[0].id; // set the selected ID to the 1st variation
I have checked through the debugger, and can see that all the correct properties are available.
selected:Object
type:Object
vehicle: "Truck"
plant:Object
id:26
price:"52"
regular_price:"100"
selected_variation:421
variations:Array[2]
0:Object
id:420
name:"small"
price:52000
regular_price:52000
1:Object
etc...
I have a computed property, which should update the plant_price based on the value of selected.plant.selected_variation.
I grab selected.plant.selected_variation and search through the variations to retrieve the price. If no variation exists, then the plant price is given.
I have a method on each product to update the selected plant. Clicking the product populates the selected.plant and triggers the computed plant_price to update the price (as the value of selected.plant.selected_variation has changed).
However, the computed plant_price is not triggered by the select. Selecting a new variant does what its supposed to, it updates selected.plant.selected_variation. Yet my plant_price doesn't seem to be triggered by it.
So I refactored my code by un-nesting selected.plant.selected_variation. I now hang it off the data object as
data = {
selected_variation: ''
}
and alter my computer property to reference the data as this.selected_variation. My computed property now works??? This makes no sense to me?
selected.plant.selected_variation isn't reactive and VM doesn't see any changes you make to it, because you set it after the VM is already created.
You can make it reactive with Vue.set()
When your AJAX is finished, call
Vue.set(selected, 'plant', {Plant Object})
There're two ways you can do it, what you are dealing with is a nested object, so if you want to notify the changes of selected to the others you have to use
this.$set(this.selected, 'plant', 'AJAX_RESULT')
In the snippet I used a setTimeout in the created method to simulate the Ajax call.
Another way you can do it is instead of making plant_price as a computed property, you can watch the changes of the nested properties
of selected in the watcher, and then update plant_price in the handler, you can check out plant_price_from_watch in the snippet.
Vue.component('v-select', VueSelect.VueSelect);
const app = new Vue({
el: '#app',
data: {
plant_price_from_watch: 'not available',
selected: {
type: {a: '' , b: ''},
vehicle: "Truck"
}
},
computed: {
plant_price() {
return this.setPlantPrice();
}
},
watch: {
selected: {
handler() {
console.log('changed');
this.plant_price_from_watch = this.setPlantPrice();
},
deep: true
}
},
created() {
setTimeout(() => {
this.$set(this.selected, 'plant', {
id: 26,
price: '52',
regular_price: '100',
selected_variation: 421,
variations: [
{
id: 420,
name: "small",
price: 52000,
regular_price: 52000
},
{
id: 421,
name: "smallvvsvsfv",
price: 22000,
regular_price: 22000
}
]
})
}, 3000);
},
methods: {
setPlantPrice() {
if (!this.selected.plant) {
return 'not available'
}
if (this.selected.plant.variations.length > 0 ) {
const variant = _.find(this.selected.plant.variations, {id: this.selected.plant.selected_variation });
return variant.price;
} else {
return this.selected.plant.price;
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<p>£{{plant_price}}</p>
<p>£{{plant_price_from_watch}}</p>
<div v-if="selected.plant && selected.plant.variations.length > 0 ">
<select v-model="selected.plant.selected_variation" class="form-control">
<!-- inline object literal -->
<option v-for="(variation, i) in selected.plant.variations" :selected="variation.id == selected.plant.selected_variation ? 'selected' : ''":value="variation.id">
{{variation.name}}
</option>
</select>
</div>
</div>

VueJS2: Control logic using JSON?

I am a newbie to JavaScript. I am trying to figure out what is the best way to write the control logic for my application. I have a list of checkboxes that hide and show different elements depending on certain options that are checked.
For example, I have the following HTML:
<label>
<input type="checkbox" name="productType" value="magazines" v-model="selectedProductType"> Magazines
</label>
<label>
<input type="checkbox" name="productType" value="books" v-model="selectedProductType"> Books
</label>
<label>
<input type="checkbox" name="productType" value="comics" v-model="selectedProductType"> Comics
</label>
<label>
<input type="checkbox" name="productType" value="videos" v-model="selectedProductType"> Videos
</label>
...snip...
And then I am hiding/showing things based on the checkmarked items
above, like so (this is just one example of some of the conditions I need to check):
<section v-if="(selectedOffice.jira) && (selectedProductType == 'comics') || (selectedProductType == 'videos')" id="booksInfo">Some info here</section>
...snip...
The issue is that I have to check different values in the data/model that looks like this:
//selectedOffice: '',
selectedProductType: [],
officeList: [
{
code: 'Blue Office',
jira: true
},
{
code: 'Red Office',
jira: false
}
...snip...
],
productList: [
{
type: 'comics',
url: 'www.comicsurl.com'
},
{
type: 'videos',
url: 'www.videosurl.com'
}
....snip...
]
Does anyone have any advice on the best way to approach the logic for my application? Better flexibility? My plan is to use an API for the data (Wordpress JSON REST API) and I will be able to customize the key/value properties on my own, but need help with the conditional stuff.
Thanks for any help!
Instead of using v-model, use #click or v-on:click to handle the click event instead. I like to keep most logic inside Vue instead of in the HTML so I recommend making use of methods and computed to determine what data to show.
const app = new Vue({
el: '#app',
data: {
selectedProductTypes: {
magazines: false,
books: false,
comics: false,
videos: false
},
productList: [],
typeList: [
{
type: 'magazines',
name: 'Magazines',
text: 'Check out new magazines'
},
{
type: 'books',
name: 'Books',
text: 'Check out new books'
},
{
type: 'comics',
name: 'Comics',
text: 'Check out new comics'
},
{
type: 'videos',
name: 'Videos',
text: 'Check out new videos'
}
]
},
computed: {
dataToBeShown() {
return this.productList
.filter(product => this.selectedProductTypes[product.type] === true) || [];
}
},
created() {
// get json data here
// assignning data here for demo
this.productList = [
{
type: 'magazines',
url: 'www.magazineurl.com'
},
{
type: 'books',
url: 'www.booksurl.com'
},
{
type: 'comics',
url: 'www.comicsurl.com'
},
{
type: 'videos',
url: 'www.videosurl.com'
}
]
},
methods: {
selectProductType(input) {
this.selectedProductTypes[input] = !this.selectedProductTypes[input];
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<div class="control">
<div v-for="item in typeList">
<label>
<input type="checkbox" #click="selectProductType(item.type)"> <b>{{item.name}}</b>&nbsp<span>{{item.text}}</span>
</label>
</div>
</div>
<hr/>
<section v-for="item in dataToBeShown">
<div>Type: {{item.type}}</div>
<div>Url: {{item.url}}</div>
</section>
</div>

Dynamically add value if fields status is changed

I'm wondering if this is possible or not. When the user hits the save button, I want knockout to check if the field labeled Status has been changed to Completed - then I want it to enter the current date into the Date Completed field.
Here are my fields -
<ul class="button-group">
<li><button data-bind="click: save" class="success">Save</button></li>
<li><button data-bind="click: saveAndClose" class="success">Save and close</button></li>
<li><button data-bind="click: cancel" class="alert">Cancel</button></li>
</ul>
<div data-bind="with: item">
<label for="Type">Type</label>
<input id="Type" data-bind="value: Type" disabled="disabled" type="text" />
<label for="Status">Status</label>
<select id ="Status" data-bind="value: Status">
<option value="Not Started">Not Started</option>
<option value="In Progress">In Progress</option>
<option value="Completed">Completed</option>
</select>
<label for="Subject">Subject</label>
<input id="Subject" data-bind="value: Subject" type="text"/>
<label for="Content">Content</label>
<textarea id="Content" data-bind="value: Content" type="text"></textarea>
label for="DateCreated">Date Created (DD/MM/YYYY)</label>
<input id="DateCreated" disabled data-bind="valueFormat: DateCreated, type: 'datetime', format: 'DD/MM/YYYY'" type="text" placeholder="Enter date in format DD/MM/YYYY" />
<label for="DateLastModified">Date Last Modified (DD/MM/YYYY)</label>
<input id="DateLastModified" data-bind="valueFormat: DateLastModified, type: 'datetime', format: 'DD/MM/YYYY'" type="text" placeholder="Enter date in format DD/MM/YYYY" />
<label for="DateCompleted">Date Completed (DD/MM/YYYY)</label>
<input id="DateCompleted" data-bind="valueFormat: DateCompleted, type: 'datetime', format: 'DD/MM/YYYY'" type="text" placeholder="Enter date in format DD/MM/YYYY" />
</div>
And heres what my js file consists of so far
var Module = function(){
var self = this;
var updateItem = function(item) {
if (item) {
self.setupEntityValidation(item, self);
self.item(item);
}
};
self.title = ko.observable();
self.item = ko.observable();
self.isLoadingData = ko.observable(true);
self.entityName = 'Task';
self.entityId = null;
self.activate = function(cid, idOrNew, newType) {
var loadedItem,
types = {
task: {
type: 'Task',
newStatus: 'Not Started'
},
phone: {
type: 'Phone',
newStatus: 'Completed'
},
email: {
type: 'Email',
newStatus: 'Completed'
},
note: {
type: 'Note',
newStatus: 'Completed'
}
},
now = null,
mode = 'new' === idOrNew ? 'Create new' : 'Edit';
// Page title
self.entityId = 'new' === idOrNew ? 0 : parseInt(idOrNew);
self.title(mode + ' task');
if ('new' !== idOrNew) {
// Load the item
self.isLoadingData = ko.observable(true);
ds.getEntityWithKey('Task', self.entityId)
.then(function(data) {
if (data && data.entity) {
// Load item
updateItem(data.entity);
} else {
log.error('#todo get by id failed with result', data);
}
})
.fail(function(err) {
log.error('#todo get by id failed completely', err.stack);
})
.finally(function() {
self.isLoadingData(false);
});
} else {
// No id, create new. Check newType is valid
if (types.hasOwnProperty(newType)) {
// Create new task
now = new Date();
loadedItem = ds.createEntity('Task', {
CentreID: parseInt(cid),
Type: types[newType].type,
Status: types[newType].newStatus,
DateCreated: now.toISOString()
});
if (loadedItem) {
updateItem(loadedItem);
} else {
log.error('Could not create new task item');
}
} else {
log.error('Cannot create new task, illegal type:' + newType);
}
self.isLoadingData(false);
}
};
};
var moduleInstance = new Module();
modex.addComponent('EntitySaveCancel', moduleInstance);
modex.addComponent('EntityValidation', moduleInstance);
return moduleInstance;
});
If you want to instantly apply the change when the field changes to "Completed" you can add a subscribe function that watches the observable "Status" for any change:
self.Status.subscribe(function (value) {
if (value === "Completed") {
//Change date here.
}
});
If you want to change it upon clicking save, you can check "Status" observable value there and set the date accordingly.
Please let us know if this works with you.

how to use form.$addControl()

I am using Angular 1.0.8. How do you correctly add compiled form elements? I assume it has to do with how to use $addControl?
Consider this example: http://jsfiddle.net/lesouthern/LB4Tx/
After adding the select in this example, the form becomes valid only if "myInput" is entered, it does not recognize the "required" directive with the appended select.
<div ng-app="pageModule"
ng-controller="parentCtrl">
<script type="text/ng-template" id="myTemplate">
<select name="mySelect"
add-to-form
ng-model="val"
required
ng-options="o.id as o.name for o in options">
<option value="">Select my option...</option>
</select>
</script>
<form name="myForm"
id="myForm"
novalidate
ng-submit="mySubmit()">
<input name="myInput"
ng-model="myInput"
required />
<div id="dest"></div>
<button type="submit">Click me to submit</button>
{{myForm.$invalid}}
</form>
<button ng-click="mkSelect()">create select</button>
</div>
var pageModule = angular.module('pageModule',[])
.controller('parentCtrl',function($scope,$compile) {
$scope.options = [
{ id : "nissan", name: "Nissan" },
{ id : "toyota", name: "Toyota" },
{ id : "fiat" , name: "Fiat" },
{ id : "chevy", name: "Chevy" },
{ id : "honda", name: "Honda" },
{ id : "gmc" , name: "GMC" }
];
$scope.mkSelect = function() {
var dest = angular.element(document.getElementById('dest')),
html = angular.element(document.getElementById('myTemplate')).html().trim();
dest.append($compile(html)($scope));
}
$scope.mySubmit = function() {
console.log('this is my submit');
}
})
.directive('addToForm',function() {
return {
require : ['ngModel'],
controller : function() {},
link : function($scope,$element,$attr,$ctrls) {
var modelCtrl = $ctrls[0];
$scope.myForm.$addControl(modelCtrl);
}
}
});
form.$addControl() was unnecessary. I corrected my compile command and the appended element now is registering with the form controller: http://jsfiddle.net/lesouthern/8CDNc/
$scope.mkSelect = function() {
var dest = angular.element(document.getElementById('dest')),
html = angular.element(document.getElementById('myTemplate')).html().trim();
$compile(html)($scope,function(_element,_scope) {
dest.append(_element);
});
}
In case you didn't need to $compile your html, you can use the ng-show directive to hide the <select> until needed. Notice it is still required
JSFiddle with no $compile
<form>
...
<select name="mySelect" id="multipleSelect" ng-show="mkSelected"
ng-model="data.singleSelect" required>
<button type="submit">Click me to submit</button>
</form>
<button ng-click="mkSelected=true">Create Select</button>

Categories