Changing exists rule based on choosen option - javascript

So i have this simple code to input value based on database value in registration form and it's work great,
The code below located at register.blade.php
This for selecting branch
<div class="form-group form-material floating">
<select class="form-control" name="branch" id="branch">
<option value="1">Option A</option>
<option value="2">Option B</option>
</select>
<label class="floating-label" for="inputStatus">Branch</label>
</div>
This one for inputing reference
<div class="form-group form-material floating {{ $errors->has('reference') ? ' has-error' : '' }}">
<input type="text" class="form-control empty" id="reference" name="reference">
<label class="floating-label" for="inputStatus">Reference</label>
#if ($errors->has('reference'))
<span class="help-block">
<strong>{{ $errors->first('reference') }}</strong>
</span>
#endif
</div>
the code below located atRegisterController.php
And this one for validation
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'phone' => 'required|string|min:5|max:20',
'rate' => 'required',
'product' => 'required',
'branch' => 'required',
'reference' => [
'required',
Rule::exists('references')->where(function ($query) {
if( 'branch' == 1 ){
$query->where('references.type', '=', "TOP");
}
else{
$query->where('references.type', '=', "BOTTOM");
}
}),
],
]
);
}
In registration form when user choose the first option on branch, the user can only write (Example : 'ABC', 'DEF', 'GHI') if the user write another value it will return Error Message : 'Wrong reference code', but when the user choose second option on branch, the user can only write (Example : '123', '456', '789'), , does anyone have and idea how to do it? Thanks
Edit 1 :
The code above works fine, but the exists rule for reference is not working, user still able to input 'ABC', 'DEF', or 'GHI' when choosing second option.
Edit 2 :
I also have this custom validation inside register.blade.php
fields: {
reference: {
validators: {
notEmpty: {
message: 'Reference must be filled'
},
stringLength: {
max: 8,
message: 'Max 8 character'
}
}
}
}

For this you need Custom Validation .Custom Validation . and about query, you can do that inside
public function passes($attribute, $value){
//value will have your reference value
//Logic here and return true/false
}
public function message()
{
//error message
//return "The :attribute value doesnt exist.";
}
and if you want to pass parameters in custom rule then you need to use constructor and use it . i.e
protected $customParams;
public function __construct($customParams)
{
$this->customParams = $customParams;
}
and rules would look like this
'reference' => ['required',new CustomRule('customvalue')]
Hope this helps.

You can make custom validation. So you can move this extra validation inside your custom validation. May be it can solve your problem.
Refer this for more on custom validation: Laravel custom validation
Hope it helps:)

Related

How can I pass a param to a custom validator?

I have the below custom validator, which is working great when passed to my input like this:
<select id="salesOwnerIdInput" v-model="currentCompany.salesOwnerId" name="salesOwnerId"
v-validate.immediate="{ 'required': salesOwnerRequired, 'contains': !userHasPlanAccess }"
:class="{'form-control': true, 'is-invalid': errors.has('main-tab.salesOwnerId') }"
data-vv-as="Sales Owner"
data-vv-scope="main-tab">
<option value="">- Select -</option>
<option v-for="option in ownerList" v-bind:value="option.id" v-bind:key="option.id">
{{ option.name }}
</option>
</select>
But as soon as I try to add a param
v-validate.immediate="{ 'required': salesOwnerRequired, 'contains:test': !userHasPlanAccess }"
I get this stupid error
vee-validate.esm.js:290 Uncaught (in promise) Error: [vee-validate] No such validator 'contains:test' exists.
What am I doing wrong??
const ContainsValidator = {
params: [
'message'
],
getMessage(field, args) {
return 'get message from args';
},
validate(value, args) {
return false;
}
}
I tried adding the param name to my registration, but it has no effect - I'm not sure if this even makes sense?
VeeValidate.Validator.extend("contains", ContainsValidator, { paramNames: ['message'] });
I am using vee-validate 2.1.4
I managed to solve it by calling the validator like this
v-validate.immediate="`required:${salesOwnerRequired}|contains:testMessage,${salesOwnerHasPlanAccess}`"
So passed the entire ruleset as a string, and interpolated anything that needed to be passed down

Console.log shows my element as an array instead of an element

I'm doing a view where the customer is able to edit items, it comes with a filter so he/she can select between the options given. Everytime I edit it and save it works, however, if I return to the edit section the text box is empty and even though it was saved. If i use the inspect tool, the Console shows this:
impuestos_compra: Array [ {…} ]
If I open it, this is the information displayed:
impuestos_compra: (1) […]
"$$hashKey": "object:87"
0: Object { id: 2, empresa_id: 6, nombre: "IVA", … }
​​
length: 1
​​
<prototype>: Array []
This is the <DIV> label where I display this:
<div class="form-group col-md-6">
<label>
Impuestos de Mario
</label>
<select ng-model="articulo.impuestos_compra" name="impuestos_compra" class="form-control input-lg" required>
<option value="">Seleccione impuesto de compra</option>
<option ng-repeat="item in impuestos_compra" value="#{{ item.abreviacion }}">#{{ item.abreviacion }}</option>
</select>
</div>
In my try to iterate it, I did this code:
impuestos_compra = ['IVA' , 'IVAT0' ];
impuestos_compra.forEach(function(impuestos_compra) {
console.log(impuestos_compra);
});
And, finally, the controller from Laravel with the edit function looks like this:
public function edit($id)
{
$articulo = Articulo::with('sat_producto:clave,descripcion', 'sat_unidad:clave,descripcion')->findOrFail($id);
return view('panel.configuracion.articulo', [
'id' => $id,
'presentaciones' => Presentacion::select('nombre')->get()->toArray(),
'impuestos_compra' => Impuesto::select('abreviacion')->where('tipo' , 'compra')->get(),
]);
What am'I doing wrong? I tried ->get()->toArray() and it works neither.
Thanks in advance.
I think the problem is in your impuestos_compra initialization. You can try pluck instead of select. Pluck returns the value of the column as a collection. Try the following code.
public function edit($id)
{
$articulo = Articulo::with('sat_producto:clave,descripcion', 'sat_unidad:clave,descripcion')->findOrFail($id);
return view('panel.configuracion.articulo', [
'id' => $id,
'presentaciones' => Presentacion::select('nombre')->get()->toArray(),
'impuestos_compra' => Impuesto::where('tipo' , 'compra')->pluck('abreviacion')->toArray(),
]);
}

how can I do "twoDataBinding" with formControlName? similar with ng Model

I'm setting a model with form, but I have a problem to set a "MyModel" with a form
This is for the purpose of optimizing the handling of the forms
public myModel = new MyModel();
this.myForm = this.formBuilder.group({
firstName: new FormControl({
value: this.myModel.firstName,
disabled: false
}),
middleName: new FormControl({
value: this.myModel.middleName,
disabled: false
}),
lastName: new FormControl({
value: this.myModel.lastName,
disabled: false
}),
age: new FormControl({
value: this.myModel.age,
disabled: false
})
});
when I submit a "submit" with a button, that shows me the "this.myForm" with the elements that I added in the form
but it seems that I would not be establishing a connection as a "TwoDataBinding"
I also do not want to do this code since I see it very redundant
also
when it comes to many forms and even worse if you decide to change or refactor the attributes of that object
this.myModel.firstName = this.myForm.controls['firstName'].value;
this.myModel.lastName = this.myForm.controls['lastName'].value;
this.myModel.middleName = this.myForm.controls['middleName'].value;
this.myModel.age = this.myForm.controls['age'].value;
You can see the complete code here:https://stackblitz.com/edit/form-model-hammer
of a form model, if you want to make changes makes a FORK to share, thanks:
also for the purpose of avoiding this alert in the picture
If you want to use 2-way binding, you should use template-driven forms instead. It allows you to use ngModel to create two-way data bindings for reading and writing input-control values.
The principles of reactive forms follows the 'one-way' rule, whereby you follow an immutable method of managing the state of your forms, such that there is greater separation of concern between your template and component logic. You can read more about the advantages of reactive forms on the above link.
If you think reactive forms is not what you want, you should revert to using template driven forms, as stated on the first paragraph.
One thing to take note, you should not use ngModel with reactive forms, as this will defeat the purpose of immutability.
However, if you are planning to stick to using reactive forms, you can simplify your code by doing this instead:
1) Initialising and declaring your reactive forms.
this.myForm = this.formBuilder.group({
firstName: [{value: this.myModel.firstName, disabled: true}],
middleName: [this.myModel.middleName],
lastName: [this.myModel.Name],
age: [this.myModel.age],
});
2) Get reactive form data:
// since the properties of myModel and myForm FormControl names are the same
this.myModel = {...this.myForm.value};
3) Update reactive form data:
this.myForm.patchValue(this.myModel);
You should stop using ngModel with Reactive forms as it is deprecated now .
You can simplify the code like below :
this.myModel.firstName= 'FIRST NAME';
this.myForm = this.formBuilder.group({
firstName:[{
value: this.myModel ? this.myModel.firstName : '',
disabled: false
}],
middleName: [{
value: this.myModel ? this.myModel.middleName : '',
disabled: false
}],
lastName: [{
value: this.myModel ? this.myModel.lastName : '',
disabled: false
}],
age:[{
value: this.myModel ? this.myModel.age : '',
disabled: false
}]
});
Listen to (ngOnSubmit) event and write a function to save the form values .
This can be achieved in the below way :
save(myForm : any){
let form = myForm as MyModel;
console.log(form);
form.otherProperties = 'nothing';
}
Or :
save(myForm : MyModel){
let form = JSON.parse(JSON.stringify(myForm)); //for copy
console.log(form);
form.otherProperties = 'nothing';
console.log( 'added a new property', form);
}
And in your html :
<div>
<form [formGroup]="myForm" (ngSubmit)='save(myForm.value)'>
<label>
<span>
Fisrt name:
</span>
<input type="text" formControlName="firstName">
</label>
<label>
<span>
Middle name
</span>
<input type="text" formControlName="middleName">
</label>
<label>
<span>
Last name
</span>
<input type="text" formControlName="lastName">
</label>
<label>
<span> Age: </span>
<input type="number" formControlName="age">
</label>
<div style="display: block">
<button (click)="onShowModel()">
show model
</button>
</div>
<div style="display: block">
<button>
set model from form
</button>
</div>
</form>
</div>
<div>
<p class="red"> from model : </p>
<span class="red"> Model: {{myModel | json}} {{nothing}}</span>
</div>
<div>
<p class="blue"> from form, binding model : </p>
<span class="blue"> Model: {{myForm.value | json}}</span>
</div>
I have also forked your example : Example

Fetch Data and Populate in Text Boxes if Selected Dropdown Option

QUESTION UPDATED WITH CURRENT STATUS
I'm using Laravel 5.7 & VueJs 2.5.* ...
I want to autofill my form textboxes with the values in database when i select dropdown option. i've been finding solution since days but didn't get any success. I'm very new at this.
WHAT I WANT TO DO:
I have two invoices VendorInvoice and CustomerInvoice…
I created my VendorInvoice, fill all data and store in DB…
But when i want to create CustomerInvoice, i need to fetch & autofill the same data which i filled and stored in DB for VendorInvoice.
So when i create CustomerInvoice, I have a <select> options of VendorInvoice _no, by selecting any option CustomerInvoice form fields should auto fill with the VendorInvoice & VendorInvoiceItems data.
So i don’t have to fill same data by myself again in CustomerInvoice…
In my code:
VendorInvoice = ticketInvoice && VendorInvoiceItems = ticketInvoiceItems
CustomerInvoice = ctInvoice && CustomerInvoiceItems = ctInvoiceItems
If anyone could help to get me out from this issue i'll be very grateful. Thank You.
Here Is my HTML <select> & some ctInvoice & ctInvoiceItems fields which i want to autofill:
<form #submit.prevent="editmode ? updateCtInvoice() : createCtInvoice()">
<div class="modal-body">
<div class="row">
<!-- =====VENDOR INVOICE SELECTION===== -->
<select id="ticket_invoice_no" v-model="selectedTicketInvoiceId" #change="getRecord" name="ticket_invoice_no" type="text" class="form-control">
<option v-for="ticketInvoice in ticketInvoices" :key="ticketInvoice.id" :value="ticketInvoice.id">{{ ticketInvoice.ticket_invoice_no }}</option>
</select>
<!-- =====CUSTOMER TICKET INVOICE NUMBER===== -->
<input v-model="form.ct_invoice_no" type="text" name="ct_invoice_no" class="form-control">
<!-- =====CUSTOMER TICKET INVOICE ITEMS===== -->
<tbody>
<tr v-for="(ctInvoiceItem, key) in form.ctInvoiceItems" :key="key">
<!--Passenger Name-->
<td>
<input v-model="ctInvoiceItem.ct_passenger_name" size="40" type="text" name="ct_passenger_name" class="table-control form-control">
</td>
<!--Ticket No.-->
<td>
<input v-model="ctInvoiceItem.ct_ticket_no" size="24" type="text" name="ct_ticket_no" class="table-control form-control">
</td>
<!--Flight No.-->
<td>
<input v-model="ctInvoiceItem.ct_flight_no" size="7" type="text" name="ct_flight_no" class="table-control form-control">
</td>
</tbody>
My #change="getRecord" method:
getRecord: function(e) {
axios
.get("api/ticket-invoice/fetch/" + this.selectedTicketInvoiceId)
.then(({
data
}) => {
console.log(data);
this.form = data; // assumes the data keys maps directly to the form properties!!
})
.catch(error => {
console.log(error.response);
});
}
Route:
Route::get('ticket-invoice/fetch/{ticket_invoice}', 'API\TicketInvoiceController#fetch')->name('ticket-invoice.fetch');
My fetch(){} method:
public function fetch($id) {
$ticketInvoices = TicketInvoice::findOrFail($id);
return response() ->json([
'id' => '',
'customer_id' => '',
'ct_invoice_no' => $ticketInvoices->ticket_invoice_no,
'ct_invoice_date' => $ticketInvoices->ticket_invoice_date,
'ct_invoice_fares_total' => $ticketInvoices->ticket_invoice_fares_total,
'ct_invoice_grand_total' => $ticketInvoices->ticket_invoice_grand_total,
'ctInvoiceItems' => $ticketInvoices->ticketInvoiceItems->map(function($item) {
return [
// get the relevant $item->property for each key below
'id' => "",
'ct_invoice_id' => "",
'ct_passenger_name' => $item->passenger_name,
'ct_fares' => $item->fares,
'ct_sub_total' => $item->sub_total
];
}) ->all()
]);
}
My data() in Vue Component:
data() {
return {
editmode: true,
selectedTicketInvoiceId: false,
ticketInvoices: {},
ctInvoices: {},
customers: null,
form: new Form({
id: "",
customer_id: "",
ct_invoice_no: "",
ct_invoice_date: "",
ct_invoice_fares_total: 0,
ct_invoice_grand_total: 0,
ctInvoiceItems: [{
id: "",
ct_invoice_id: "",
ct_passenger_name: "",
ct_fares: 0,
ct_sub_total: 0
}]
})
};
},
When i select option i see in my Vue Component that specific id data fill in my form:. but its not actually fill my input fields with that data, so i could do some changes in the data and finally store it in DB as a customerInvoice.
Vue Dev Tool BEFORE SELECTING OPTION:
Vue Dev Tool AFTER SELECTING OPTION:
BUT NOT FILLING FIELDS:
I don't know Laravel 5.7 or vue but the concept remains the same
1- I would give an example of what I would do, I'll make a php file that has a select * from database and echo the result in json
2- Then use ajax, fetch to the php file and get that json, I will use the data retrieved in the javascript file
3 - I will have a function like on Dropdown Option onclick fetch or ajax, make the dropdown options equal to to the json fetched.

How to validate array inputs using proengsoft/laravel-jsvalidation and Laravel 5

Hi I'm trying to validate an array input and select like this:
<td width="23%">
{!!Form::select('mmscod_id[]',['' => '- Seleccione un material -'] +$mat,null,['class' => 'form-control', 'id'=>'mmscod_id'])!!}
</td>
<td width="17%">
<input type="text" class="form-control" id="cantidad" name="vtcanp[]"/>
</td>
<td width="17%">
<input type="text" class="form-control" id="precio" name="vtprep[]"/>
</td>
I'm using the proengsoft/laravel-jsvalidation for client-side validation. For the back-end I use Laravel's Form request.
I also use the method of this site: How To: Validate an array of form fields with Laravel but it doesn't work and throws errors:
error1
error2
Edit:
I forgot to mention that these elements are created dynamically
Please help me
Laravel supports validating array inputs. You need to use this convention to validate array item.
$rules = [
'vtcanp.*' => 'required',
];
For example:
This is my custom request class
class InvoiceRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules =[
'client' => 'required',
'date' => 'required',
'total' => 'required',
'discount' => 'required',
'item.*' => 'required',
'rate.*' => 'required',
'quantity.*' => 'required',
];
return $rules;
}
}
And in the view added
{!! JsValidator::formRequest('App\Http\Requests\InvoiceRequest') !!}
These validate and show the error message with position of input array that I dynamically added to the view.

Categories