Form Validation with ngClass and AngularJS not working - javascript

I am new to angular and am trying (and failing) to get the ngClass to work with some validation on a basic contact form.
I want to highlight the inputs when they are in the success/error by highlighting with bootstrap 'has-error' and 'glyphicon-remove' classes if there are any issues with the data.
my form is as follows;
<form class="row instant-quote-form" ng-controller="formCtrl" ng-cloak>
<div class="col-md-12">
<h2>Quick Form</h2>
<div class="form-group has-feedback">
<div class="input-group col-md-12">
<label for="titleSelect" class="input-group-addon">Title :</label>
<select name="titleSelect" id="titleSelect" class="form-control"
ng-model="form.titleResult" required>
<option value="">Select Title...</option>
<option ng-repeat="option in titles" value="{{option.name}}">{{option.name}}</option>
</select>
</div>
<div class="input-group col-md-12" ng-class="{ 'has-error': form.name.$invalid, 'text-success' : form.name.$valid}">
<label for="nameInput" class="input-group-addon">Name :</label>
<input type="text" class="form-control" id="nameInput" placeholder="Full Name..." ng-model="form.name" required>
<span ng-class="{ 'glyphicon-remove' : form.name.$invalid, 'glyphicon-ok' : form.name.$valid }" class="glyphicon form-control-feedback"></span>
</div>
<div class="input-group col-md-12">
<label for="postcodeInput" class="input-group-addon">Postcode :</label>
<input type="text" class="form-control" id="postcodeInput" placeholder="Postcode..." ng-model="form.postcode" required>
<span class="glyphicon form-control-feedback"></span>
</div>
<div class="input-group col-md-12">
<label for="emailInput" class="input-group-addon">Email :</label>
<input type="email" class="form-control" id="emailInput" placeholder="Email Address..." ng-model="form.email" required>
<span class="glyphicon form-control-feedback"></span>
</div>
<div class="input-group col-md-12">
<label for="telephoneInput" class="input-group-addon">Telephone :</label>
<input type="text" class="form-control" id="telephoneInput" placeholder="Telephone Number..." ng-model="form.telephone" required>
<span class="glyphicon form-control-feedback"></span>
</div>
<div class="input-group col-md-12">
<label for="timeSelect" class="input-group-addon">To to Call :</label>
<select name="timeSelect" id="timeSelect" class="form-control"
ng-model="form.timeResult" required>
<option value="">Select Time...</option>
<option ng-repeat="option in times" value="{{option.name}}">{{option.name}}</option>
</select>
</div>
<div class="col-md-12">
<button type="submit" class="btn btn-primary btn-block" ng-click="submit(form)">Request Callback!</button>
</div>
</div>
</div>
</form>
my controller is as follows;
'use strict';
app.controller('formCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.titles =
[
{ id: '1', name: 'Mr.' },
{ id: '2', name: 'Mrs.' },
{ id: '3', name: 'Master.' },
{ id: '4', name: 'Miss.' },
{ id: '5', name: 'Sir.' },
{ id: '6', name: 'Dr.' },
{ id: '7', name: 'Other.' }
];
$scope.times =
[
{ id: '1', name: 'Morning.' },
{ id: '2', name: 'Afternoon.' }
];
$scope.submit = function (form) {
console.log(form);
};
}]);
However, the ngclass directive is not being applied? also it seems that the submit is being called even when the form is invalid? do I need to validate the form fromthe controller as well?

Add a name attribute and value to your form tag & input...
<form name="form" class="row instant-quote-form" ng-controller="formCtrl" ng-cloak>
&
<input name="name" type="text" class="form-control" id="nameInput" placeholder="Full Name..." ng-model="name" required>
because when you refer to form.name in 'has-error': form.name.$invalid it works based off of the name of the form and the name of the input box
Note there is a conflict using form.name as your ng-model based upon your controller you will want ng-model="name"
Here is a working plnkr

Related

Vue.js cli insert and show data

I'm trying to create a form, the user insert data and i should show the data in another page just using vue js
I wrote this form
<form
id="main-contact-form"
class="contact-form row"
name="contact-form"
method="post"
>
<div class="form-group col-md-6">
<input
v-model="this.$store.state.name"
type="text"
name="name"
class="form-control"
required="required"
placeholder="اسم المنتج"
/>
</div>
<div class="form-group col-md-6">
<input
v-model="this.$store.state.price"
type="text"
name="email"
class="form-control"
required="required"
placeholder="السعر"
/>
</div>
<div class="form-group col-md-6">
<select
name="subject"
class="form-control"
v-model="this.$store.state.sub"
>
<option value="1">اكسسوريز</option>
<option value="2">عنايه</option>
<option value="3">مكياج</option>
<option value="4">شنط</option>
<option value="5">عطور</option>
<option value="6">اجهزه</option>
<option value="7">ملابس نساء</option>
<option value="8">رجال</option>
</select>
</div>
<div class="form-group col-md-6">
<input
:value="img"
type="file"
name="image"
class="form-control"
placeholder="اختر صورة المنتج"
/>
</div>
<div class="form-group col-md-12">
<textarea
v-model="this.$store.state.message"
name="message"
id="message"
required="required"
class="form-control"
rows="8"
placeholder="وصف المنتج أو نبذة عنه"
></textarea>
</div>
<div class="form-group col-md-12">
<input
#submit.prevent="this.$store.state.add"
type="submit"
name="submit"
class="btn btn-primary pull-right"
value="اضافة"
/>
</div>
</form>
this is my data and function i import them from store
export default createStore({
state: {
name: "",
price: "",
sub: "",
img: "",
message: "",
date: "new Date(Date.now()).toLocaleString()",
pro: [],
add: function () {
var New = {
nName: this.name,
nPrice: this.price,
nSub: this.sub,
nImg: this.img,
nDate: this.date,
};
this.name = "";
this.price = "";
this.sub = "";
this.pro.push(New);
alert(5);
// this.$router.push("/control-panel");
},
},
mutations: {},
actions: {},
modules: {},
});
When I press the button, i have this error
( Cannot POST /add-new-product ),
what should i do or what's the wrong with my code
"add" function should not be at "state" object but moved into "actions"
since it calls (as I can guess) an api to save the object
"generally if you want to modify/mutate your state, you do that in functions declared in mutations:{} and if you make api calls which are asychronous operations you declare functions in actions:{}"
e.x.
export default createStore({
actions:{
add:function(context,params){
return new Promise(function(resolve){
//call your api with ajax, assume that it returns correct
//commit your object to "add" function of mutations
context.commit('add',params);
});
}
}
})
after "add" actions returns successfully from the "api" request then you should have another
"add" function in mutations which will mutate your "pro" attribute of state
and any other "state" attributes/properties
e.x.
mutations:{
add:function(state,obj){
state.name = "";
state.price = "";
state.sub = "";
state.pro.push(obj);
alert(5);
}
}
rewrite also your vue "Form" component by adding an "submit" method (which will call the "store action") as follows and move to the "form" tag
<template>
<form #submit.prevent="submit"
id="main-contact-form"
class="contact-form row"
name="contact-form"
method="post"
>
<div class="form-group col-md-6">
<input
v-model="this.$store.state.name"
type="text"
name="name"
class="form-control"
required="required"
placeholder="اسم المنتج"
/>
</div>
<div class="form-group col-md-6">
<input
v-model="this.$store.state.price"
type="text"
name="email"
class="form-control"
required="required"
placeholder="السعر"
/>
</div>
<div class="form-group col-md-6">
<select
name="subject"
class="form-control"
v-model="this.$store.state.sub"
>
<option value="1">اكسسوريز</option>
<option value="2">عنايه</option>
<option value="3">مكياج</option>
<option value="4">شنط</option>
<option value="5">عطور</option>
<option value="6">اجهزه</option>
<option value="7">ملابس نساء</option>
<option value="8">رجال</option>
</select>
</div>
<div class="form-group col-md-6">
<input
:value="img"
type="file"
name="image"
class="form-control"
placeholder="اختر صورة المنتج"
/>
</div>
<div class="form-group col-md-12">
<textarea
v-model="this.$store.state.message"
name="message"
id="message"
required="required"
class="form-control"
rows="8"
placeholder="وصف المنتج أو نبذة عنه"
></textarea>
</div>
<div class="form-group col-md-12">
<input
type="submit"
name="submit"
class="btn btn-primary pull-right"
value="اضافة"
/>
</div>
</form>
</template>
<script>
export default{
methods:{
submit:function(){
this.$store.dispatch("add", {
nName: this.$store.state.name,
nPrice: this.$store.state.price,
nSub: this.$store.state.sub,
nImg: this.$store.state.img,
nDate: this.$store.state.date,
});
}
}
}
</script>
you can find a working example here
https://codesandbox.io/s/vuex-store-forked-d8895

Calling a method in itself as a method

So , basically i am trying to create a input field and when i enter a number it gives me the desired child of the same html.
now i want child to produce more children with unique name with javascript.
i am attaching the code for a better understanding.
<div class="row" id="child_nr">
<div class="col-xs-12">
<div class="form-group col-xs-6">
<div class="form-group col-xs-4">
<label for="name" class="control-label">Parameter Name: <font color="red">*</font></label>
</div>
<div class="form-group col-xs-8">
<input type="text" class="form-control required" id="param_name" name="param_name" placeholder="name" onblur="param()"/>
</div>
</div>
<div class="form-group col-xs-6">
<div class="form-group col-xs-3">
<input type="text" class="form-control required" id="parent_nr" name="parent_nr" value="0" onblur="param()"/>
</div>
<div class="form-group col-xs-5">
<label for="name" name="service_code" id="service_code" class="control-label">
Service Code </label>
</div>
<div class="form-group col-xs-4">
<input type="text" class="form-control required" name="service_code" id="service_code"/>
</div>
</div>
</div>
</div>
<script language="javascript">
function param(){
var value=parent_nr.value;
const name=document.getElementById("param_name").value;
for(var i=1;i<=value;i++)
{
const html='<div class="col-xs-12"><div class="form-group col-xs-6"><div class="form-group col-xs-7"><label for="name" class="control-label">Parameter Name'+i+': <font color="red">*</font></label></div><div class="form-group col-xs-5"><input type="text" class="form-control required" id="name" name="name" placeholder="name"/></div></div><div class="form-group col-xs-6"><div class="form-group col-xs-3"><input type="number" class="form-control required" id="parent_nr" name="parent_nr" value="0" onblur="param()"/></div><div class="form-group col-xs-5"><label for="name" name="service_code" id="service_code" class="control-label">Service Code </label></div><div class="form-group col-xs-4"><input type="text" class="form-control required" name="service_code" id="service_code"/></div></div></div>';
document.querySelector('#child_nr').insertAdjacentHTML('beforeend',html);
}
}
function sendData() {
var question = 'abc';
var c = 'cde';
$.ajax({
url: 'http://localhost/gtiemr/addnewparameter_laboratory',
type: 'POST',
data: { question: question, c: c },
success: function () {
alert('suc');
},
error: function (error) {
alert('error');
}
});
}
</script>
Also, i want to know how i can send the value to my controller using ajax so that i can send it to model.

Angular display ngFor value in another tag

I have list of comapnies which I display like that:
<div class="col-md-4">
<select ngModel="selectedCompany" style="width:400px;">
<option *ngFor="let x of mycompanylist" value="{{x.id}}">{{x.name}}
</option>
</select>
<input class="form-control" type="text" formControlName="CompanyID" value = "{{selectedCompany}}">
</div>
I need the value of selected option to be displayed in input tag. I tried to do it with ngModel but it doesnt work.
The main purpose is to pass the value to formControlName so after form is submitted I can recieve the value but if I do it like this:
<option *ngFor="let x of mycompanylist" value="{{x.id}}" fromControlName="ComapnyID">
the options are no longer displayed
UPDATE
I fixed it using [(ngModel)] and getting rid of formControlName.
Here's a Working Sample StackBlitz for ref.
UPDATE
Form:
<div class="col-md-4">
<select class="form-control" [(ngModel)]="selectedCompany">
<option *ngFor="let x of mycompanylist" [value]="x.id">{{x.name}}
</option>
</select>
</div>
<form [formGroup]="invoiceForm" (ngSubmit)="save()" #formDir="ngForm" novalidate>
<div class="form-group row">
<label class="control-label col-md-12" for="name">CompanyID</label>
<div class="col-md-4">
<input class="form-control" type="text" formControlName="CompanyID" value ="{{selectedCompany}}">
</div>
<span class="text-danger" *ngIf="invoiceForm.hasError('required', 'CompanyID') && formDir.submitted">
CompanyID is required.
</span>
</div>
<div class="form-group row">
<label class=" control-label col-md-12" for="description">VendorID</label>
<div class="col-md-4"> <input class="form-control" type="text" formControlName="VendorID"> </div>
</div>
<div class="form-group"> <button type="submit" class="btn btn-default">Save</button> <button class="btn" (click)="cancel()">Cancel</button> </div>
</form>
Error:
A quick solution could be sharing the same model
<div class="col-md-4">
<select [(ngModel)]="selectedCompany" style="width:400px;">
<option *ngFor="let x of mycompanylist" [value]="x.name">{{x.name}}
</option>
</select>
<input class="form-control" type="text" [(ngModel)]="selectedCompany">
</div>
So if the user typing in the field also update the model of the select.
Another solution could be to use ngModelChange
<div class="col-md-4">
<select [(ngModel)]="selectedCompany" style="width:400px;" (ngModelChange)="onSelectedCompany($event)">
<option *ngFor="let x of mycompanylist" [value]="x.name">{{x.name}}
</option>
</select>
<input class="form-control" type="text" [(ngModel)]="company" readonly>
</div>
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
selectedCompany: string = null;
company: string = null;
mycompanylist = [
{ id: 1, name: 'Company 1' },
{ id: 2, name: 'Company 2' },
{ id: 3, name: 'Company 3' },
{ id: 4, name: 'Company 4' }
];
onSelectedCompany(company: string) {
this.company = company;
}
}
Important to highlight the read-only attribute so that the user can not enter anything

How would I be able to multiple select and pass data in the given format in vue js html?

I need to pass the data in the given format.
rules : [{
name:null,
section:null,
data : [{head:null,value:null}]
}],
This is the problem I am facing. Hope somebody could help me sort out a solution. The snippet is given. I need to pass data in the format given above. If another array is needed inside rules[], it is also fine
Is another array needed for head and value inside data[]. This will be also fine, if needed. Hoping for a help. Please help me to have a solution.
Please change the select to read the issues
addForm = new Vue({
el: "#addForm",
data: {
rules: [{
name: null,
section: null,
data: [{
head: null,
value: null
}]
}],
},
methods: {
addNewRules: function() {
this.rules.push({
name: null,
section: null,
data: [{
head: null,
value: null
}]
});
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="addForm">
<div class="card-content" v-for="(bok, index) in rules" :key="index">
<p>This is the first part which is fine for me</p>
<div class="row">
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label">Act</label>
<select class="form-control" v-model="bok.name">
<option value="Act,1972">Act,1972</option>
<option value="Rule,2012">Rule,2012(CEMR)</option>
<option value="Act,1961">Act,1961</option>
</select>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label">Section</label>
<input type="text" class="form-control" v-model="bok.section">
</div>
</div>
<div class="row" v-if="bok.name == 'Act,1972'">
<p>When selecting Act,1972 is here rules.data.head. Fine for me</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Arms</label>
<input type="text" class="form-control" v-model="bok.data[0].head" required="">
</div>
</div>
</div>
<div class="row" v-if="bok.name == 'Rule,2012'">
<p>When Selecting Rule,2012 HOW TO PASS values rules.data.head in this case . There are two input fields here???</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Item</label>
<input type="text" class="form-control" v-model="bok.data[0].head" required="">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Quantity Seized</label>
<input type="text" class="form-control" v-model="bok.data[0].head" required="">
</div>
</div>
</div>
<div class="row" v-if="bok.name == 'Act,1961'">
<p>When selecting Act,1931 Its a select option, I need to select multiple options from here and pass values as rules.data.head. //After I select multiple options I have input fields corresponding to the options. This to be send as rules.data.value.. How
to do this?</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Select</label>
<select class=" form-control" v-model="bok.data[0].head" multiple="">
<option value="1">life</option>
<option value="2">Enment</option>
</select>
</div>
</div>
</div>
<div class="row" v-if="bok.data[0].head == 1">
<p>If option is 1, i should display this and pass value as rules.data.value . HERE THERE ARE TWO INPUT FIELDS How to pass the values</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Area1</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Area2</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value">
</div>
</div>
</div>
<div class="row" v-if="bok.data[0].head == 2">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">No.</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Model</label>
<input type="text" class="form-control" required="">
</div>
</div>
</div>
</div>
<a #click="addNewRules">Add Another Rule</a>
</div>
My approach is basically change the type of the data[0].head and data[0].value depending on the options you selected.
So for example, if you select Rule,2012, then data[0].head would be an object with item and qty as its items. And if you select Act,1961, data[0].head would be an array of numbers (e.g. ['1', '2']) and data[0].value would be an object with area_1 and area_2 or number and model or all the four items.
See and try the code snippet to see the code I added/changed.
(Or compare your code with mine and you'd see the changes.)
addForm = new Vue({
el: "#addForm",
data: {
rules: [{
name: null,
section: null,
data: [{
head: null,
value: null
}]
}],
},
methods: {
addNewRules: function() {
this.rules.push({
name: null,
section: null,
data: [{
head: null,
value: null
}]
});
},
removeRuleDataValueProps: function(i) {
var d = this.rules[i].data[0];
if (jQuery.inArray('1', d.head) < 0) {
Vue.delete(d.value, 'area_1');
Vue.delete(d.value, 'area_2');
}
if (jQuery.inArray('2', d.head) < 0) {
Vue.delete(d.value, 'number');
Vue.delete(d.value, 'model');
}
},
_setRuleDataHeadDataType: function(i) {
var d = this.rules[i].data[0],
h = d.head,
_h = d._head,
_restore = true;
if (undefined === _h) {
d._head = h;
_restore = false;
}
switch (this.rules[i].name) {
case 'Rule,2012':
var a = Array.isArray(h);
if (a || null === h || 'object' !== typeof h) {
Vue.set(d, 'head', {});
}
break;
case 'Act,1961':
if (!Array.isArray(h)) {
Vue.set(d, 'head', []);
}
break;
default:
if (_restore && undefined !== _h) {
d.head = _h;
}
break;
}
},
_setRuleDataValueDataType: function(i) {
var d = this.rules[i].data[0],
v = d.value,
_v = d._value,
_restore = true;
if (undefined === _v) {
d._value = v;
_restore = false;
}
switch (this.rules[i].name) {
case 'Act,1972':
case 'Act,1961':
var a = Array.isArray(v);
if (a || null === v || 'object' !== typeof v) {
Vue.set(d, 'value', {});
}
if (_restore) {
this.removeRuleDataValueProps(i);
}
break;
default:
if (_restore && undefined !== _v) {
d.value = _v;
}
break;
}
},
setRuleDataType: function(i, k) {
if (this.rules[i] && this.rules[i].data[0]) {
if (!k || 'head' === k) {
this._setRuleDataHeadDataType(i);
}
if (!k || 'value' === k) {
this._setRuleDataValueDataType(i);
}
}
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="addForm">
<h3>Try the different options and see the JSON output changes.</h3>
<div class="card-content" v-for="(bok, index) in rules" :key="index">
<p>This is the first part which is fine for me</p>
<div class="row">
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label">Act</label>
<!-- Here we change the type of `bok.data[0].head` depending on the selected option. -->
<select class="form-control" v-model="bok.name" #change="setRuleDataType(index)">
<option value="Act,1972">Act,1972</option>
<option value="Rule,2012">Rule,2012(CEMR)</option>
<option value="Act,1961">Act,1961</option>
</select>
</div>
</div>
<!--</div>-->
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label">Section</label>
<input type="text" class="form-control" v-model="bok.section">
</div>
</div>
<!-- Here, `bok.data[0].head` is expected to be a `string`. -->
<div class="row" v-if="bok.name == 'Act,1972'">
<p>When selecting Act,1972 is here rules.data.head. Fine for me</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Arms</label>
<input type="text" class="form-control" v-model="bok.data[0].head" #change="setRuleDataType(index, 'value')" required="">
</div>
</div>
</div>
<!-- Here, `bok.data[0].head` is an `object` with 'item' and 'qty'. -->
<div class="row" v-if="bok.name == 'Rule,2012'">
<p>When Selecting Rule,2012 HOW TO PASS values rules.data.head in this case . There are two input fields here???</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Item</label>
<input type="text" class="form-control" v-model="bok.data[0].head.item" required="">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Quantity Seized</label>
<input type="text" class="form-control" v-model="bok.data[0].head.qty" required="">
</div>
</div>
</div>
<!-- Here, `bok.data[0].head` would be an array of numbers. -->
<div class="row" v-if="bok.name == 'Act,1961'">
<p>When selecting Act,1931 Its a select option, I need to select multiple options from here and pass values as rules.data.head. //After I select multiple options I have input fields corresponding to the options. This to be send as rules.data.value.. How
to do this?</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Select</label>
<select class=" form-control" v-model="bok.data[0].head" #change="removeRuleDataValueProps(index)" multiple="">
<option value="1">life</option>
<option value="2">Enment</option>
</select>
</div>
</div>
</div>
<div class="row" v-if="jQuery.inArray('1', bok.data[0].head) > -1">
<p>If option is 1, i should display this and pass value as rules.data.value . HERE THERE ARE TWO INPUT FIELDS How to pass the values</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Area1</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value.area_1">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Area2</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value.area_2">
</div>
</div>
</div>
<div class="row" v-if="jQuery.inArray('2', bok.data[0].head) > -1">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">No.</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value.number">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Model</label>
<input type="text" class="form-control" required="" v-model="bok.data[0].value.model">
</div>
</div>
</div>
<h3>The JSON value of <code>bok</code></h3>
<textarea rows="3" cols="75%" readonly>{{ JSON.stringify(bok) }}</textarea>
</div>
<a #click="addNewRules">Add Another Rule</a>
</div>
My opinion,
Based on the HTML you provied, create one data property=ruleTemplate (it makes sure v-model with related form controls).
When add new rules, push one clone of the template to the rules
When you need the data, just convert the rules to the specific format like
this.getFormattedRules in below demo.
Below is the demo:
addForm = new Vue({
el: "#addForm",
data: {
ruleTemplates: {
name: '',
section: '',
subMenu: {
'Act,1972': '',
'Rule,2012': {'item': '','qty': ''},
'Act,1961': {'head':[], options:{'option1':'', 'option2':''}}
}
},
rules: [{
name: '',
section: '',
subMenu: {
'Act,1972': '',
'Rule,2012': {'item': '','qty': ''},
'Act,1961': {'head':[], options:{'option1':'', 'option2':''}}
}
}
],
},
computed: {
formatedJson: function () {
let handler1972 = function (data) {
return [{'head': 'Arms', 'value': data}]
}
let handler2012 = function (data) {
return [{'head': 'item', 'value': data.item},{'head': 'qty', 'value': data.qty}]
}
let handler1961 = function (data) {
return [{'head': 'option1', 'value': data.options.option1},{'head': 'option1', 'value': data.options.option2}]
}
let handlers = {'Act,1972': handler1972, 'Rule,2012': handler2012, 'Act,1961': handler1961
}
return this.rules.map((rule) => {
let formatedRule = new Object()
// convert the rule to the specific format
formatedRule.name = rule.name
formatedRule.section = rule.section
handler = handlers[rule.name]
formatedRule.data = handler ? handler(rule.subMenu[rule.name]) : []
return formatedRule
})
}
},
methods: {
addNewRules: function() {
this.rules.push(Object.assign({},this.ruleTemplates))
}
}
})
.show-format {
position:absolute;
top:2px;
right -4px;
background-color:gray
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="addForm">
<div class="show-format">Format: {{formatedJson}}</div>
<div class="card-content" v-for="(bok, index) in rules" :key="index">
<p>This is the first part which is fine for me</p>
<div class="row">
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label">Act</label>
<select class="form-control" v-model="bok.name">
<option value="Act,1972">Act,1972</option>
<option value="Rule,2012">Rule,2012(CEMR)</option>
<option value="Act,1961">Act,1961</option>
</select>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label">Section</label>
<input type="text" class="form-control" v-model="bok.section">
</div>
</div>
<div class="row" v-if="bok.name == 'Act,1972'">
<p>When selecting Act,1972 is here rules.data.head. Fine for me</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Arms</label>
<input type="text" class="form-control" v-model="bok.subMenu['Act,1972']" required="">
</div>
</div>
</div>
<div class="row" v-if="bok.name == 'Rule,2012'">
<p>When Selecting Rule,2012 HOW TO PASS values rules.data.head in this case . There are two input fields here???</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Item</label>
<input type="text" class="form-control" v-model="bok.subMenu['Rule,2012']['item']" required="">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Quantity Seized</label>
<input type="text" class="form-control" v-model="bok.subMenu['Rule,2012']['qty']" required="">
</div>
</div>
</div>
<div class="row" v-if="bok.name == 'Act,1961'">
<p>When selecting Act,1931 Its a select option, I need to select multiple options from here and pass values as rules.data.head. //After I select multiple options I have input fields corresponding to the options. This to be send as rules.data.value.. How
to do this?</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Select</label>
<select class=" form-control" v-model="bok.subMenu['Act,1961'].head" >
<option value="1">life</option>
<option value="2">Enment</option>
</select>
</div>
</div>
</div>
<div class="row" v-if="bok.subMenu['Act,1961'].head == 1">
<p>If option is 1, i should display this and pass value as rules.data.value . HERE THERE ARE TWO INPUT FIELDS How to pass the values</p>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Area1</label>
<input type="text" class="form-control" required="" v-model="bok.subMenu['Act,1961'].options.option1">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Area2</label>
<input type="text" class="form-control" required="" v-model="bok.subMenu['Act,1961'].options.option2">
</div>
</div>
</div>
<div class="row" v-if="bok.subMenu['Act,1961'].head == 2">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">No.</label>
<input type="text" class="form-control" required="" v-model="bok.subMenu['Act,1961'].options.option1">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Model</label>
<input type="text" class="form-control" required="" v-model="bok.subMenu['Act,1961'].options.option2">
</div>
</div>
</div>
</div>
<a #click="addNewRules" style="background-color:green">Add Another Rule</a>
</div>
hey why don't you go with multi-select checkbox drop-down and apply v-model on checkbox. ?
Link: How to use Checkbox inside Select Option

How to submit form with partially read only inputs with jQuery?

I made a form in jQuery + Django which has only one input active and the others are read only. There is a button which when clicked activates all the input boxes and the whole form is then editable. However, before clicking the button only one input is there and I want to be able to submit the form in that state. But I want all the other values to be submitted too, as they are readonly that should not be a problem.
Here's my JS:
$('#addInventoryForm').on('submit', function(event) {
event.preventDefault();
$('#name').focus();
add_to_inventory();
});
function add_to_inventory() {
console.log("add to inventory is working!")
$.ajax({
url : "/new/item/add/",
type : "POST",
data : { upc : $('#upc').val(), name : $('#name').val(), qty : $('#qty').val(), add_qty : $('#add_qty').val(), reorder_qty : $('#reorder_qty').val(), dp : $('#dp').val(), mrp : $('#mrp').val(), supplier : $('#supplier').val() },
success : function(data) {
console.log(data);
$('#extra').html(data);
console.log("success");
}
});
}
The url in the above code points to the following view:
def NewItemAdd(request):
if request.method == "POST":
upc = request.POST['upc']
name = request.POST['name']
if 'qty' in request.POST:
qty = request.POST['qty']
add_qty = request.POST['add_qty']
reorder_qty = request.POST['reorder_qty']
dp = request.POST['dp']
mrp = request.POST['mrp']
if 'supplier' in request.POST:
supplier = Supplier.objects.get(name=request.POST['supplier'])
if 'qty' not in request.POST:
qty = 0
if 'supplier' in request.POST:
defaults = {'name': name, 'qty': int(qty) + int(add_qty), 'reorder_qty': reorder_qty, 'dp': dp, 'mrp': mrp, 'supplier': supplier, 'user': request.user}
else:
defaults = {'name': name, 'qty': int(qty) + int(add_qty), 'reorder_qty': reorder_qty, 'dp': dp, 'mrp': mrp, 'user': request.user}
inv, created = Item.objects.update_or_create(upc=upc, defaults=defaults)
supplier_list = Supplier.objects.all()
return render(request, "alpha/new-item-add.html", {'suppliers': supplier_list})
The template used with this view is as follows:
<div class="container">
<div class="form-group">
<label class="control-label col-xs-1" for="name">Name:</label>
<div class="col-xs-9">
<input type="text" class="form-control" id="name" name="name" placeholder="" tabindex="2"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-1" for="qty">Current Quantity:</label>
<div class="col-xs-2">
<input type="number" class="form-control" id="qty" name="qty" placeholder="" readonly/>
</div>
<label class="control-label col-xs-1" for="add_qty">Add Quantity:</label>
<div class="col-xs-2">
<input type="number" class="form-control" id="add_qty" name="add_qty" placeholder="" tabindex="3"/>
</div>
<label class="control-label col-xs-offset-1 col-xs-1" for="reorder_qty">Reorder Quantity:</label>
<div class="col-xs-2">
<input type="number" class="form-control" id="reorder_qty" name="reorder_qty" placeholder="" tabindex="4"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-1" for="dp">DP:</label>
<div class="col-xs-2">
<input type="text" class="form-control" id="dp" name="dp" placeholder="" tabindex="5"/>
</div>
<label class="control-label col-xs-1" for="mrp">MRP:</label>
<div class="col-xs-2">
<input type="text" class="form-control" id="mrp" name="mrp" placeholder="" tabindex="6"/>
</div>
<label class="control-label col-xs-offset-1 col-xs-1" for="reorder_qty">Supplier:</label>
<div class="col-xs-2">
<select name="supplier" id="supplier" class="btn btn-default form-control" tabindex="7">
{% for supplier in suppliers %}
<option value="{{ supplier }}" {% if supplier.name == item.supplier.name %}selected{% endif %}>{{ supplier.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<div class="col-xs-offset-1 col-xs-9">
<input type="submit" value="Submit" class="form-control btn btn-primary" tabindex="8"/>
</div>
</div>
</div>
I want to be able to submit the form when the inputs are readonly as well as when I click a button and activate all the inputs. Can anyone find anything wrong with the above code?
The edit button removes the readonly attribute from all the inputs of the form. So before submitting the form I trigger a click on the edit button. It's almost instantaneous and the problem is solved.
$("#edit").trigger("click");

Categories