Validate dynamic input field in vue.js - vue.js

I have a table in which I add the input field dynamically and I set the validation manually by using Toastr notifications . what the problem is that when I add the input at the first time the validation is working perfectly but when I add another input the validation is not working on new added input. I have tried and searched for the solution but I did not find any solution.Any help will be highly appreciated.
My HTML code :
<table class="table-hover" id="form">
<thead>
<tr>
<th>پلورنکی</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, $index) in rows" :key="row.id">
<td>
<input
dir="rtl"
id="supplier_id1"
v-model="row.supplier_id1"
placeholder="نیټه "
type="text"
name="supplier_id1"
class="form-control"
/>
</td>
</tr>
</tbody>
</table>
<button
class="btn btn-success btn-xs"
#click="getData()"
>
خوندی کړی
</button>
My script code :
export default {
data() {
return {
rows: [
{
supplier_id1: "",
}
],
}
}
methods: {
getData: function() {
if (this.rows[0].supplier_id1 == "") {
toast.fire({
icon: "warning",
html: "<h5> supplier id is required.</h5>"
});
} else {
//if the input is not emptyexecute the coed successfully
}
}
}
}

You will always check for the first row, because of if (this.rows[0]...)
rows[0] will always take the first object in your array
If you always want to validate all the rows, you could check if there are any rows without a supplier id: if (this.rows.filter((row) => row.supplier_id1 === "").length)

I not sure which toast component did you used, but i can do similar mock for your validation message + databinding of your {{row.supplier_id1}}
v-model value of input[type="date] will only valid when you inputted date correctly so this.rows[0].supplier_id1.length == 0 to validate is fine. The reactivity is working fine.
My Working Fiddle: https://jsfiddle.net/bu9twps2/
UPDATE: Your original condition to validate works fine as well, problem likely lies at your toast

Related

Vue js: How to add a class to the closest td on click of Button

I am new to Vue coming off of JS/JQuery. I have a table, and each row has 2 possible buttons and two inputs, all wrapped in <td>. When I click a button I want the nearest input to have a class added. In JQuery I would have used the closest method in selecting the neighbouring <td> Here is my Vue template syntax. Many thanks!
<tbody>
<tr v-for="child in registeredChildren">
<td class="col-2"><a :href="'/getchild/'+ child.child_id">{{child.childFirstName}}</a>&nbsp &nbsp {{child.childLastName}}</td>
<!--========TIME IN===========-->
<td class="col-3 pb-2"}"><input style="text-align:center;" class="form-control editChild initial" type="text" v-model="child.timeIn" ></td>
<td><button v-on:click="updateTimeIn(child)" class="btn btn-outline-success">Reset</button></td>
<!-- //========TIME Out ===========//-->
<td class="col-3 pb-2" ><input style="text-align:center;" class="form-control editChild" type="text" v-model="child.timeOut" ></td>
<td><button v-on:click="updateTimeOut(child)" class="btn btn-outline-success">Reset</button></td>
</tr>
</tbody>
Methods: I was thinking if I could add some code to the UpdateTimeIn and TimeOut methods, this could be an approach?
methods:{
updateTimeIn(child){
this.updatedChild = child;
console.log(child.child_id,child.timeIn)
axios.post('http://kidsclub.test/upDateChildTimeIn', {
child_id: child.child_id,
timeIn: child.timeIn,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},
**NB** I have the same for updateTimeOut
You are using Vue, which unlike jQuery, means the data should drive the DOM. In Vue, you don’t have to consider selecting certain dom nodes.
I used to switch from jQuery to Vue, too. I have provided a demo, hope you can find ideas in it.
<button #click="onClick">click me</button>
<div class="fixed-classes" :class="{'dynamic-class': isClick}"></div>
data() {
return {
isClick: false
};
},
methods: {
onClick() {
this.isClick = !this.isClick;
}
}
You can run it online through the code sandbox link: codesandbox
I updated the code based on the comments in the code sandbox.

The v-model in the view is not updated until after reloading the page for the first time

Because when updating the value of a variable in the method, it is not updated in the v-model of the view ?.
If I reload the page the method v-on: change ="reCalcTotal(index, art.stock_solicited)" works correctly, and updates the subtotal value every time "art.stock_solicited" changes.
But until I reload the page for the first time, the method does not modify the v-model in the view.
What alternative do I have to solve it?
HTML
<tr v-for="(art, index) in arGeneratedOrders" v-if="art.stock_solicited > 0">
<td>
$#{{ art.subtotal.toFixed(1) }}
<input type="text" v-model="art.subtotal">
</td>
<td>
<input type="number" v-model="art.stock_solicited" v-on:change="reCalcTotal(index, art.stock_solicited)">
</td>
</tr>
<tr>
<td>
Total: $#{{total.toFixed(2)}}
</td>
</tr>
js
data: {
arGeneratedOrders:''
},
computed: {
total(){
let total=0;
this.arGeneratedOrders.forEach(item => {
total += item.subtotal;
});
return total
}
},
methods: {
reCalcTotal: function(index, newStockSolicited) {
this.arGeneratedOrders[index].stock_solicited=newStockSolicited;
this.arGeneratedOrders[index].subtotal=(this.arGeneratedOrders[index].stock_solicited)*this.arGeneratedOrders[index].purchase_price,
localStorage.setItem('lsGeneratedOrders', JSON.stringify(this.arGeneratedOrders));
this.total;
alert('Index:'+index+' - New:'+newStockSolicited+' - ='+this.arGeneratedOrders[index].subtotal); //This alert shows the updated variables, but the values do not change in the view.
}
}

dynamically add input as well as dropdown in vuejs

I m trying to add a dynamical input along with dropdown for that i m using vue-serach-select let me show my code then issue in detail
<template>
<button #click="addRow1"></button>
<table class="table table-striped">
<thead>
<tr style="font-size: 12px; text-align: center;">
<th class="span2" >Product Name</th>
<th class="span2" >Unit</th>
</tr>
</thead>
<tbody id="product_table_body">
<tr v-for="(row, index) in rows">
<td><model-list-select :list="productname"
option-value="product_name"
option-text="product_name"
v-model="row.selectproduct"
placeholder="Search Product Name"
#searchchange="searchprd3">
</model-list-select>
</td>
<td>
<input class="form-control-sm" type="text" v-model="row.new1" disabled="disabled" style="width: 100px;">
</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
data () {
return {
productname3:[],
rows:[],
}
},
methods:{
addRow1(){
this.rows.push({})
},
searchprd3(search,index){
},
}
}
</script>
now if i click on button one more row is added with dropdown now my problem is that how i can differentiate productname according to dynamic create row i had tried like :list="productname{index},:list="productname.index but none of them worked and last thing i want to pass index parameter in searchprd3 function so i tried like this searchprd3(search,index) in function I m getting index but it throw error for search and if only pass index then also throw error however it work none of parameter is passed from select like this #searchchange="searchprd3" but in function i m not getting index value or is there anyother way to achieve this thing
updated
<tr v-for="(row, index) in rows">
<td><model-list-select :list="row.productname"
option-value="product_name"
option-text="product_name"
v-model="row.selectproduct"
placeholder="Search Product Name"
#searchchange="searchprd3">
</model-list-select>
</td>
</tr>
<script>
searchprd3(searchText,index){
var _this=this
this.$http.get('/api/companyproducts?filter[where][product_name][ilike]=%'+searchText+'%').then(function (response) {
_this.rows.push({productname:response.data})
}).catch(function (error) {
console.log("error.response");
});
},
</script>
i want select option list seprate for every row but my code throw error like "Cannot read property 'map' of undefined"
that is why row push not working for dynamic row is I m missing Something
update2
found my mistake
addRow1(){
this.rows.push({
productnamex:[],
unit:'',
qty:'',
amt:'',
cgst:'',
sgst:'',
igst:''})
},
problem is that i haven't initialize my dropdown at rows click now another problem is that why my drop not get populated
try like this
<template>
<model-list-select :list="row.productnamex"
option-value="product_name"
option-text="product_name"
v-model="row.selectproduct"
placeholder="Search Product Name"
#searchchange="searchprd3($event,index,row)" >
</model-list-select>
</template>
<script>
addRow1(){
console.log(this.rows)
this.rows.push({ productnamex:[],unit:'', qty:'',amt:'', cgst:'', sgst:'', igst:''})
},
searchprd3(searchText,index,row){
console.log(index)
var _this=this
console.log(row)
this.$http.get('/api/companyproducts?filter[where][product_name][ilike]=%'+searchText+'%').then(function (response) {
console.log(response.data)
row.productnamex=response.data
}).catch(function (error) {
console.log("error.response");
});
},
</script>
hope this will help you as well as other enjoy :D
you should be able to do:
:list="productname+index"
You need to manually pass the index into the callback together with the searchtext in order for your searchprd3 method to receive both values.
This is where the inline $event variable in your event listener comes into the action. The $event variable contains the value that is supposedly passed to your callback by the event.
So if you want to pass additional data into the callback aside from the data that is passed by the event, you can manually call the callback function and pass the $event together with the data that you want to pass which in this case, the index variable.
Your event listener should look like this:
#searchchange="searchprd3($event, index)"

pass value to method from dynamic input field vuejs

I have a dynamic table with some input field and button in each row. I want to pass each row individual value when i click the button. Can anyone help me how to do it?
HTML:
<tr v-for="(item, index) in items">
//other Data
<td><input v-model="item1"></td>
<td><input v-model="item2"></td></td>
<td><button #click="doSomething()">send</button></td>
</tr>
javascript:
methods: {
doSomething() {
//values from each input field
}
}
Just pass index as a parameter to the function.
<button #click="doSomething(index)">send</button>
then in the method
doSomething(index) {
//values from each input field
}

Dynamically added rows to table does not the get the Dojo style

I am working in ASP.Net MVC4 with Dojo. I have a strange problem when I am adding new rows to html table. I need to have a table which supports adding and removing rows and textboxes inside should have dojo style. I referred the post http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ ad tried to create the same thing. Let me explain my code. Below is my view
#section scripts {
<script type="text/javascript">
require(["dojo/parser", "dijit/form/TextBox", "dijit/form/Button"]);
</script>
}
<table id="servicesTable">
<tr>
<th>
<label id="lblSelectService">
Select</label>
</th>
<th>
<label id="lblServiceName">
Name</label>
</th>
<th>
<label id="lblTitle">
AE Title</label>
</th>
</tr>
#for (int i = 0; i < Model.Services.Count; i++)
{
#Html.Partial("_ServiceRow", Model.Services[i])
}
</table>
My partial view for rendering each row is like below
#model WebUI.Models.RemDevServiceViewModel
<tr>
<td>
#Html.CheckBoxFor(x => x.IsMarked,
new { id = #String.Format("Service[{0}]IsMarked", #Model.ID) })
</td>
<td>
<input style="width: 100px; id="Service[#Model.ID]Name"
name="Service[#Model.ID].Name" type="text"
data-dojo-type="dijit/form/TextBox" value="#Model.Name"/>
</td>
<td>
<input style="width: 100px;" id="Service[#Model.ID]Title"
data-dojo-type="dijit/form/TextBox"
name="Service[#Model.ID].Title" type="text"
value="#Model.Title" />
</td>
</tr>
I have an add button which will add new row to the table. The problem that I am facing is, new row does not get the dojo style and they are rendered as normal textboxes. Initially loaded rows are rendered as dojo style text boxes, but the newly added are not like that. My jquery function to add new rows is like below
function addNewService() {
$.ajax({
url: rootPath + "MyController/AddNewService",
type: "get",
cache: false,
success: function (html) {
$("#servicesTable tbody").append(html);
},
error: function (ts) {
alert("Error while adding services");
}
});
}
Can any one tell me how to solve this? Please note that I am aware about the existence of Dojo grid. I want to take the advantage of model binding and hence following this style
Try running the parser over the added nodes. Are you seriously loading jquery on the page as well? Anyway, with the code you've got, it's kind of tricky to select the just added nodes, but if you put the following inside the success method it might work.
var newNodes = $(html).appendTo("#servicesTable tbody");
require(["dojo/parser"], function(parser){
newNodes.forEach(function(node){
parser.parse(node);
});
});
If you parse over nodes that were already parsed, the parser will throw an error. Also, if you need to support older browsers you'll want to replace the forEach with a standard for loop.
Thanks a lot David for your reply. Your code did not work exactly, but I got the idea and below code is working for me. Please dont feel that I am answering my own question. I want to format the code properly and hence using this view. Once again thanks a lot
success: function (html) {
var newNodes = $(html).appendTo("#servicesTable tbody");
require(["dojo/_base/array", "dojo/parser"], function (array, parser) {
array.forEach(newNodes, function (node, i) {
parser.parse(node);
});
});