AlpineJs x-for passing js data to Laravel Component as props - javascript

I have select dropdown html element with two options: Enable (with value = 1) and Disable (with value = 0)
These options are provided by items props.
// component/select-input.blade.php
#props(['items' => [], 'selected' => ''])
<select {!! $attributes->merge([
'class' =>
'pr-10 py-2 rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50',
]) !!}>
#foreach ($items as $item)
#if ($item['value'] == $selected)
#php
$optionSelected = 'selected';
#endphp
#else
#php
$optionSelected = '';
#endphp
#endif
<option value="{{ $item['value'] }}" {{ $optionSelected }} #selected(old($attributes->get('name')) == $item['value'])>{{ $item['label'] }}
</option>
#endforeach
</select>
// usage
#php
$itemsBlock = [
[
'label' => 'Disabilitato',
'value' => 0,
],
[
'label' => 'Abilitato',
'value' => 1,
],
];
#endphp
<x-select-input :items="$itemsBlock" />
This code show correctly a select box.
This select is inside e x-for loop made with AlpineJS, where fields is an array of datata about these select, for example:
fields
<div x-data="{fields: [{status: 1}, {status: 0}]}">
<template x-for="(field, index) in fields" :key="index">
<x-select-input :items="$itemsBlock" />
</template>
</div>
How to pass field.status in my loop to my component x-select-input as "selected" props for provide e default selected options?
I have tried
<x-select-input class="mt-1" :items="$itemsBlock" ::selected="`${field.status}`" />
but doesn't works, any ideas?
Thx all for support!

Related

primeng checkbox with reactive form with array

I am trying to add my array of object to map the primeng checkbox and would like to get the values for selected check boxes.
I have tried FormControlName but it it's throwing undefined after submitting.
below is the rough code
data = [
{ type: dropdown
text: 'drop',
num: 1.23,
options: [
{
value=1,
text= 'drop1
},{
value=2,
text= 'drop2
}
]
},
{ type: checkbox
text: 'check',
num: 1.23,
options: [
{
value=1,
text= 'check1
},{
value=2,
text= 'check2
}
]
},
{ type: radio
text: 'radio',
num: 1.23,
options: [
{
value=1,
text= 'radio1
},{
value=2,
text= 'radio2
}
]
},
];
Template:
<form [formGroup]="group">
<div *ngFor="let d of data">
<div *ngSwitchCase = "checkbox">
<p-checkbox *ngFor="let check of options" [value]="check.value" [formControlName]="check.text"></p-checkbox>
</div>
<div *ngSwitchCase = "dropdown">
<p-dropdown *ngFor="let drop of options" [value]="drop.value" [formControlName]="d.text"> {{drop.text}}
</p-dropdown>
</div>
<div *ngSwitchCase = "radio">
<p-radioButton *ngFor="let radio of options"[value]="radio.value" [formControlName]="d.text"></p-radioButton >
</div>
</div>
</form>
How I can get the reference of my control and values the same for drop down and check boxes.
How to get the values for dynamic forms?
for reactive dynamic form first thing we have to generate the formGroup base of the form control data
getFormGroup method will return a formGroup object by loop over the data and create a form controls with name base of the text value .
getFormGroup() {
const formControls = this.data.reduce( (controls , f:FormControl)=>{
controls[f.text] = this.formBuilder.control(null);
return controls;
},{});
return this.formBuilder.group(formControls)
}
after we generate the form now we can render the form controls on the template
<form [formGroup]="form">
<div *ngFor="let d of data">
<ng-container [ngSwitch]="d.type">
<label for="">{{d.text}}</label>
<div *ngSwitchCase="'checkbox'">
<p-checkbox *ngFor="let check of d.options" [label]="check.label" [value]="check.value"
[formControlName]="d.text"></p-checkbox>
</div>
<div *ngSwitchCase="'dropdown'">
<p-dropdown [options]="d.options" [formControlName]="d.text">
</p-dropdown>
</div>
<div *ngSwitchCase="'radio'">
<p-radioButton *ngFor="let radio of d.options" [name]="d.text" [label]="radio.label"
[value]="radio.value" [formControlName]="d.text">
</p-radioButton>
</div>
</ng-container>
</div>
</form>
stackblitz demo 🚀

Laravel - How to ensure that order price is not less than product price in input field

I am using Laravel-5.8 for a web application that involves dynamic input field. The project is based on sales Order.
Model
class Product extends Model
{
protected $table = 'products';
protected $fillable = [
'name',
'rate',
'vat',
];
}
class Order extends Model
{
protected $table = 'orders';
protected $fillable = [
'date',
'customer_id',
'workOrder_id',
'details',
'product_id',
'rate',
'vat',
'quantity',
'remaining',
'amount',
];
public function customer(){
return $this->belongsTo(Customer::class, 'customer_id');
}
public function product(){
return $this->belongsTo(Product::class, 'product_id');
}
}
product_id in products is a foreign key to orders
Controller
public function create()
{
$order = null;
$products = Product::all('id','name');
$customers = Customer::all('id','name');
return view('pages.order.create', compact('order','products','customers'));
}
public function store(Request $request)
{
$request->validate([
'date' => 'required',
'customer_id' => ['required', Rule::notIn(['','0'])],
'workOrder_id' => 'required|unique:orders',
]);
for ($i=0; $i < count($request->product_id) ; $i++) {
$order = new Order;
$order->date = $request->date;
$order->customer_id = $request->customer_id;
$order->workOrder_id = $request->workOrder_id;
$order->details = $request->details;
$order->product_id = $request->product_id[$i];
$order->rate = $request->rate[$i];
$order->vat = $request->vat[$i];
$order->quantity = $request->quantity[$i];
$order->remaining = $request->quantity[$i];
$order->amount = $request->quantity[$i] * $request->rate[$i];
$order->save();
}
return redirect()
->route('order.index')
->with('success', 'Added Successfully');
}
In an order, a customer can have several products
view
<section class="content">
<div class="container-fluid">
<div class="card card-warning">
<div class="card-body">
<form method="POST" action="{{ route('order.store') }}">
#csrf
{{-- Date --}}
<div class="form-group">
<label for="date">
Date
</label>
<input type="text" class="form-control{{ $errors->has('date') ? ' is-invalid' : '' }}" name="date" id="date" value="{{ old('date', optional($order)->date) }}">
#if ($errors->has('date'))
<span class="invalid-feedback">
<strong>{{ $errors->first('date') }}</strong>
</span>
#endif
</div>
{{-- customer --}}
<div class="form-group">
<label for="customer_id">Customer</label>
<select name="customer_id" class="form-control{{ $errors->has('customer_id') ? ' is-invalid' : '' }}" id="customer_id">
<option value="">Select</option>
#foreach($customers as $customer)
<option value="{{ $customer->id }}" {{old('customer_id', optional($order)->customer_id) == $customer->id ? 'selected':''}}>{{ $customer->name }}</option>
#endforeach
</select>
#if ($errors->has('customer_id'))
<span class="invalid-feedback">
<strong>{{ $errors->first('customer_id') }}</strong>
</span>
#endif
</div>
<div class="row">
<div class="col-md-1">
<button id="add_more" class="btn btn-info mt-4"><i class="fa fa-plus" title="Add More Product"></i></button>
</div>
<div class="col-md-11">
<div id="more_product">
<div class="row">
<div class="col-md-3">
{{-- Product --}}
<div class="form-group">
<label for="product_id">Select Product</label>
<select name="product_id[]" class="form-control" id="product_id" required="required">
<option value="">Select Product</option>
#forelse($products as $product)
<option value="{{ $product->id }}" >
{{ $product->name }}
</option>
#empty
<option value="">No Product Found</option>
#endforelse
</select>
</div>
</div>
<div class="col-md-3">
{{-- Rate --}}
<div class="form-group">
<label for="rate">
Rate
</label>
<input type="number" min="0" step="any" class="form-control" name="rate[]" id="rate" required="required">
</div>
</div>
<div class="col-md-3">
{{-- Quantity --}}
<div class="form-group">
<label for="vat">
Vat
</label>
<input type="number" min="0" step="any" class="form-control" name="vat[]" id="vat" required="required">
</div>
</div>
<div class="col-md-3">
{{-- Quantity --}}
<div class="form-group">
<label for="quantity">
Quantity
</label>
<input type="number" min="0" class="form-control" name="quantity[]" id="quantity" required="required">
</div>
</div>
</div>
</div>
</div>
</div>
{{-- workOrder_id --}}
<div class="form-group">
<label for="workOrder_id">Work Order No</label>
<input type="text" class="form-control{{ $errors->has('workOrder_id') ? ' is-invalid' : '' }}" name="workOrder_id" id="workOrder_id" value="{{ old('workOrder_id', optional($order)->workOrder_id) }}">
#if ($errors->has('workOrder_id'))
<span class="invalid-feedback">
<strong>{{ $errors->first('workOrder_id') }}</strong>
</span>
#endif
</div>
{{-- Payment Type --}}
{{-- <div class="form-group">
<label for="payment">Payment</label>
<select name="payment" class="form-control{{ $errors->has('payment') ? ' is-invalid' : '' }}" id="payment">
<option value="">Select Payment</option>
<option value="1">Cash</option>
<option value="2">Due</option>
</select>
#if ($errors->has('payment'))
<span class="invalid-feedback">
<strong>{{ $errors->first('payment') }}</strong>
</span>
#endif
</div> --}}
{{-- Details --}}
<div class="form-group">
<label for="details">
Remarks
</label>
<textarea name="details" class="form-control {{ $errors->has('details') ? ' is-invalid' : '' }}" id="details" cols="30" rows="5">{{ old('details', optional($order)->details) }}</textarea>
#if( $errors->has('details'))
<span class="invalid-feedback">
<strong>{{ $errors->first('details') }}</strong>
</span>
#endif
</div>
{{-- Save --}}
<div class="form-group row mb-0">
<div class="col-md-12">
<button type="submit" class="btn btn-primary">
{{ __('Save') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
Javascript
<script>
{{-- jquery datepicker --}}
$( function() {
$( "#date" ).datepicker({
dateFormat: 'yy-mm-dd',
changeMonth: true,
changeYear: true,
});
});
$('#customer_id').select2({
placeholder: 'Select Customer',
ajax: {
url: '{!!URL::route('customer-autocomplete-search')!!}',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: data
};
},
cache: true
},
theme: "bootstrap"
});
$('#product_id').select2({
placeholder: 'Select Product',
ajax: {
url: '{!!URL::route('product-autocomplete-search')!!}',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: data
};
},
cache: true
},
theme: "bootstrap"
});
$(document).ready(function() {
var max_fields = 150;
var wrapper = $("#more_product");
var add_button = $("#add_more");
var x = 1;
$(add_button).click(function(e){
e.preventDefault();
if(x < max_fields){
x++;
$(wrapper).append('<div class="row"><div class="col-md-3">{{-- Product --}}<div class="form-group"><label for="product_id">Select Product</label><select name="product_id[]" class="form-control product_id" id="product_id" required="required"><option value="">Select Product</option>#forelse($products as $product)<option value="{{ $product->id }}" >{{ $product->name }}</option>#empty<option value="">No Product Found</option>#endforelse </select></div></div><div class="col-md-3">{{-- Rate --}}<div class="form-group"><label for="rate">Rate</label><input type="number" min="0" step="any" class="form-control" name="rate[]" id="rate" required="required"></div></div><div class="col-md-2">{{-- vat --}}<div class="form-group"><label for="vat">Vat</label><input type="number" min="0" step="any" class="form-control" name="vat[]" id="vat" required="required"></div></div><div class="col-md-3">{{-- Quantity --}}<div class="form-group"><label for="quantity">Quantity</label><input type="number" min="0" class="form-control" name="quantity[]" id="quantity" required="required"></div></div><div class="col-sm-1"><button style="margin-top: 30px;" class="btn btn-info"><i class="fa fa-minus" title="Remove Item"></i></button></div></div>');
$('.product_id').select2({
placeholder: 'Select Product',
ajax: {
url: '{!!URL::route('product-autocomplete-search')!!}',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: data
};
},
cache: true
},
theme: "bootstrap"
});
}
});
$(wrapper).on("click",".remove_field", function(e){
e.preventDefault();
$(this).parent().parent('div').remove();
x--;
})
});
</script>
I have been on this for days. What I want to achieve is that as the User enter the rate on order on a particular product, the system should compare it with the rate in products.
If the rate on order is less than that in product, the system should display an error message to the user explaining the problem.
How do I achieve this?
Thank you
Ok, so here's what I've come up. As explained earlier, this only provides server side validation as from what I can see you do not have any client side one.
First thing I did was to convert validation in the controller to a Request injected to the store method. I called it StoreOrderRequest
App\Http\Requests\StoreOrderRequest
<?php
namespace App\Http\Requests;
use App\Order;
use App\Product;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
/**
* Class StoreOrderRequest
*
* #package App\Http\Requests
*
* #property string $date
* #property int $customer_id
* #property int $workOrder_id
* #property array $product_id
* #property array $rate
* #property array $vat
* #property array $quantity
*/
class StoreOrderRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules(): array
{
return [
'date' => 'required',
'customer_id' => [
'required',
'exists:customers,id',
],
'workOrder_id' => [
'required',
'unique:orders',
],
'details' => 'present',
'product_id' => 'array',
'rate' => 'array',
'vat' => 'array',
'quantity' => 'array',
];
}
/**
* Prepare the data for validation.
*
* #return void
*/
protected function prepareForValidation(): void
{
$this->redirect = route('order');
$this->validator = $this->getValidatorInstance();
$this->validator->after(function (Validator $validator) {
$products = Product::whereIn('id', $this->product_id)->get();
foreach ($this->product_id as $key => $id) {
$rate = $products->firstWhere('id', $id)->rate;
if ($rate < $this->rate[$key]) {
continue;
}
$validator->errors()->add(
'rate.'.$key,
__(
'validation.min.numeric',
[
'attribute' => 'rate',
'min' => $rate
]
)
);
}
});
}
/**
* Create orders.
*
* #return void
*/
protected function save(): void
{
$orders = collect($this->product_id)
->map(function (int $product_id, int $index) {
return array_merge(
$this->only([
'date',
'customer_id',
'workOrder_id',
'details',
]),
[
'product_id' => $this->product_id,
'rate' => $rate = $this->rate[$index],
'vat' => $this->vat[$index],
'quantity' => $qty = $this->quantity[$index],
'remaining' => $qty,
'amount' => $qty * $rate,
]
);
});
Order::insert($orders->toArray());
}
}
You'll see that I've made use of the prepareForValidation method, which allowed us to register the after validation hooks. These check each product rate and if it's less than the corresponding Product record, it will add the error for its index to the error bag.
(Please note I've overriden the default redirect property to work with my test - you probably won't need that line if you're just going back to the previous page).
I've also created the save method that saves all these orders.
With all this, we are now able to skim your OrderController::store method significantly:
OrderController
/**
* Store new record.
*
* #param \App\Http\Requests\StoreOrderRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(StoreOrderRequest $request): RedirectResponse
{
$request->save();
return redirect()
->route('order')
->with('success', 'Added Successfully');
}
And here's the corresponding test to make sure everything above works as expected:
Tests\Feature\ProductOrderTest
<?php
namespace Tests\Feature;
use App\Order;
use App\Product;
use App\Customer;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ProductOrderTest extends TestCase
{
use RefreshDatabase;
/**
* #test
*/
public function validation_fails_with_product_rate_lower_than_original_product_price()
{
$customer = factory(Customer::class)->create();
$product_1 = factory(Product::class)->create(['rate' => 20.50]);
$product_2 = factory(Product::class)->create(['rate' => 95.67]);
$this->assertCount(0, Order::all());
$response = $this->post(route('order.store'), [
'date' => now(),
'customer_id' => $customer->id,
'workOrder_id' => 1,
'details' => 'Order details',
'product_id' => [
0 => $product_1->id,
1 => $product_2->id,
],
'rate' => [
0 => 20.49,
1 => 95.66,
],
'vat' => [
0 => round(20.49 * 0.20),
1 => round(95.66 * 0.20),
],
'quantity' => [
0 => 1,
1 => 1,
],
]);
$response->assertRedirect(route('order'));
$response->assertSessionMissing('success');
$response->assertSessionHasErrors([
'rate.0' => __('validation.min.numeric', [
'attribute' => 'rate',
'min' => 20.50
]),
'rate.1' => __('validation.min.numeric', [
'attribute' => 'rate',
'min' => 95.67
]),
]);
$this->assertCount(0, Order::all());
}
/**
* #test
*/
public function saves_order_with_valid_request()
{
$customer = factory(Customer::class)->create();
$product_1 = factory(Product::class)->create(['rate' => 20.50]);
$product_2 = factory(Product::class)->create(['rate' => 95.67]);
$this->assertCount(0, Order::all());
$response = $this->post(route('order.store'), [
'date' => $date = now(),
'customer_id' => $customer->id,
'workOrder_id' => 1,
'details' => 'Order details',
'product_id' => [
0 => $product_1->id,
1 => $product_2->id,
],
'rate' => [
0 => 20.50,
1 => 95.68,
],
'vat' => [
0 => round(20.50 * 0.20),
1 => round(95.68 * 0.20),
],
'quantity' => [
0 => 1,
1 => 1,
],
]);
$response->assertRedirect(route('order'));
$response->assertSessionHas('success', 'Added Successfully');
$response->assertSessionDoesntHaveErrors();
$this->assertCount(2, Order::all());
$this->assertDatabaseHas('orders', [
'date' => $date = now(),
'customer_id' => $customer->id,
'workOrder_id' => 1,
'details' => 'Order details',
'product_id' => $product_1->id,
'rate' => 20.50,
'vat' => round(20.50 * 0.20),
'quantity' => 1,
'remaining' => 1,
'amount' => 20.50,
]);
$this->assertDatabaseHas('orders', [
'date' => $date = now(),
'customer_id' => $customer->id,
'workOrder_id' => 1,
'details' => 'Order details',
'product_id' => $product_2->id,
'rate' => 95.68,
'vat' => round(95.68 * 0.20),
'quantity' => 1,
'remaining' => 1,
'amount' => 95.68,
]);
}
}

tag name property undefined using Vue but accessible within the browser

Currently i have a selector that returns undefined when using Vue for the {{ lens.price }}. But when i use a = lens[1].getAttribute('price') within the browser console i get the correct returned value of "0".
Why is Vue making this returned data undefined? The property works fine within the browser on all options that are returned from the for loop.
Do i need to pass both properties to a single value tag name?
HTML/LIQUID:
<div>
<label for="lens"></label>
<select id="lens" name="line_items[lens]" #change="handleChange('lens', $event); secondChange($event);"
class="mt-3 option-selector text-sm lg:text-base uppercase block appearance-none w-full bg-white text-gray-900 py-3 px-4 pr-8 rounded-sm leading-tight focus:outline-none focus:border-black font-bold">
<option>Choose a lens</option>
{% for lens in collections.lenses.products %}
<option price="{{ lens.price }}" value="{{ lens.variants[0].id }}">{{ lens.title }} |
{{ lens.price | plus: product.price | money_without_trailing_zeros}}</option>
{% endfor %}
</select>
</div>
BREAKDOWN OF VUE: (NOT COMPLETE CODE)
data: function () {
return {
buttonText: false,
slideOut: false,
disableAddToCart: true,
chosenLens: '',
chosenFilter: '',
lensPrice: ''
}
handleChange(type, e) {
if (type === 'lens') {
if (e.target.value) {
this.chosenLens = e.target.value;
}
else {
this.chosenLens = ''
}
}
if (type === 'filter') {
this.chosenFilter = e.target.value || ''
}
this.disableAddToCart = !(this.chosenLens && this.chosenFilter);
},
secondChange(e) {
this.lensPrice = `${e.target.price}`;
},
I have tried Javascript only: (undefined)
<div>
<label for="lens"></label>
<select id="lens" onchange="myFunction()" name="line_items[lens]" #change="handleChange('lens', $event);"
class="mt-3 option-selector text-sm lg:text-base uppercase block appearance-none w-full bg-white text-gray-900 py-3 px-4 pr-8 rounded-sm leading-tight focus:outline-none focus:border-black font-bold">
<option>Choose a lens</option>
{% for lens in collections.lenses.products %}
<option price="{{ lens.price }}" value="{{ lens.variants[0].id }}">{{ lens.title }} |
{{ lens.price | plus: product.price | money_without_trailing_zeros}}</option>
{% endfor %}
</select>
</div >
<h1 id="demo"></h1>
<script>
function myFunction() {
var x = document.getElementById("lens").price;
document.getElementById("demo").innerHTML = "You selected: " + x;
}
</script>
Only attribute name 'value': (working)
<div>
<label for="lens"></label>
<select id="lens" onchange="xIs()" name="line_items[lens]" #change="handleChange('lens', $event);"
class="mt-3 option-selector text-sm lg:text-base uppercase block appearance-none w-full bg-white text-gray-900 py-3 px-4 pr-8 rounded-sm leading-tight focus:outline-none focus:border-black font-bold">
<option>Choose a lens</option>
{% for lens in collections.lenses.products %}
<option value="{{ lens.price }}">{{ lens.title }} |
{{ lens.price | plus: product.price | money_without_trailing_zeros}}</option>
{% endfor %}
</select>
</div>
<h1 id="demo"></h1>
<script>
const xIs = () => {
var x = document.getElementById("lens").value;
document.getElementById("demo").innerHTML = `x is: ${x}`;
}
</script>
Let's start here:
e.target.value
e is the browser event object.
e.target will be the <select> element.
A <select> element has a built-in property called value that reflects the currently selected value. This value is taken from the value attribute of the currently selected <option>.
So what happens is:
User clicks on an <option>.
The browser sets the value attribute of the <select> to be equal to the value attribute of the selected <option>.
The browser fires the change event for the <select>.
The value attribute has special significance in HTML. Other attributes of the <option>, such as price, do not.
Here's an example that doesn't use Vue at all that exhibits this same behaviour:
document.getElementById('lens').addEventListener('change', function (ev) {
const target = ev.target
console.log(target.tagName, target.value, target.price)
})
<select id="lens">
<option value="A" price="1">First</option>
<option value="B" price="2">Second</option>
</select>
Vue does have some special handling for binding non-string values to <option> elements for use with v-model but the problem you're seeing is not specific to Vue.
I know this might not be a proper fix but i was able to just do a hack for now using split(): The problem is Vue seems to want data to come from Value and any other attribute name it didn't work with.
<option value="{{ filter.variants[0].id }}-{{ filter.price }}"><span>{{ filter.title }} +
</span><span>{{ filter.price | money_without_trailing_zeros }}</span></option>
priceMethod(type, e) {
if(type === 'lens')
if (e.target.value) {
let a = e.target.value
a = a.split("-")[1]
a = a.replace('00', '')
console.log(a)
a = parseInt(a)
this.lensPrice = a;
}
if (type === 'filter') {
let b = e.target.value
b = b.split("-")[1]
b = b.replace('00', '')
b = parseInt(b)
console.log(b)
this.filterPrice = b || ''
}
In the end i was successful with the same technique as the below.
<select id="app" #change="deleteItem()">
<option type="button" data-price="$149">
$149
</option>
<option type="button" data-price="$409">
$409
</option>
</select>
new Vue({
el: '#app',
methods:{
deleteItem: function(){
var carList = document.getElementById("app");
var selCar = carList.options[carList.selectedIndex].dataset.price;
alert(selCar)
}
},
})
The output is an alert of the data attribute of $149 on change or $409 on change. #click also works.

Vue App ID causing issues with existing page 'addEventListener'

Got a couple of issues on my html form page after adding Vue.js.
After adding the Vue ID to the form, the addEventListener seems to stop working which prevents any form submissions from the page.
<form name="myform" id="deliveryservice">
<select v-model="search">
<option disabled="disabled" value="">JSON Dayslots</option>
<option v-for="item in items" v-bind:value="item.slot">
{{ item.shortcode }} {{ item.slot }}
</option>
</select>
<select v-model="servicev" required>
<option selected disabled hidden>Please Select</option>
<option value="standard">Standard</option>
<option value="installation">Installation</option>
</select>
<div class="maxfee">
<input name="price" v-model.number="pricev" type="currency" placeholder="Max price you will pay" required>
</div>
<div class="summary"><p>Summary:</p></div>
<p class="summaryresult" style="font-weight:bold;">I would like {{ search.shortcode }} on {{ servicev }} service and pay no more than £{{ pricev }}</p>
<button type="submit">Submit</button>
</form>
<div class="loading js-loading is-hidden">
<div class="loading-spinner">
<svg><circle cx="25" cy="25" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/></svg>
</div>
</div>
<p class="js-success-message is-hidden">Thanks! You are now monitoring that share price.</p>
<p class="js-error-message is-hidden">Error!</p>
<script>
const app = new Vue({
el: '#deliveryservice',
data: {
items: [],
search: '',
dayslotvv: '',
servicev: '',
pricev: ''
},
created: function() {
fetch('https://s3.eu-west-2.amazonaws.com/dayslots10/dayslots.json')
.then(resp => resp.json())
.then(items => {
this.items = items
})
}
});
</script>
<script>
const scriptURL = 'https://script.google.com/macros/s/AKfycbwBJJPS5kY3o17bj_Nc6DIx8KTnXGPa6iVjlSZ7HA/exec'
const form = document.forms['myform']
const loading = document.querySelector('.js-loading')
const successMessage = document.querySelector('.js-success-message')
const errorMessage = document.querySelector('.js-error-message')
form.addEventListener('submit', e => {
e.preventDefault()
showLoadingIndicator()
fetch(scriptURL, { method: 'POST', body: new FormData(form)})
.then(response => showSuccessMessage(response))
.catch(error => showErrorMessage(error))
})
function showLoadingIndicator () {
form.classList.add('is-hidden')
loading.classList.remove('is-hidden')
}
function showSuccessMessage (response) {
console.log('Success!', response)
setTimeout(() => {
successMessage.classList.remove('is-hidden')
loading.classList.add('is-hidden')
}, 500)
}
function showErrorMessage (error) {
console.error('Error!', error.message)
setTimeout(() => {
errorMessage.classList.remove('is-hidden')
loading.classList.add('is-hidden')
}, 500)
}
</script>
Lastly, the option selected from "JSON Dayslots" will not display in the summary at the footer of the form. I have tried a few options such as "this", "item", "search" with no joy.
Here is the form in action on my page
http://vuetest79.s3-website.eu-west-2.amazonaws.com/
In "JSON Dayslots", your v-bind:value is set to item.slot, so vue binds items.slot to search. As a result, {{ search.shortcode }} in your search summary is trying to access item.slot.search, which doesn't exist. Setting v-bind:value to just "item" should make your code work.
<select v-model="search">
<option disabled="disabled" value="">JSON Dayslots</option>
<option v-for="item in items" v-bind:value="item">
{{ item.shortcode }} {{ item.slot }}
</option>
</select>
As for your addEventListener, I'm not sure why it stops working. In your source code, your form name is myform, while the const 'form' is bound to 'submit-to-google-sheet'. Perhaps this is the problem? Although in this question, it seems to be set up correctly.
const form = document.forms['submit-to-google-sheet']
Both are working in this jsfiddle: https://jsfiddle.net/adampiziak/mrdva3kj/10/
(the listener just outputs "submitted" to the console)

Update multiple select2 field with laravel, ajax and angularJs

I have a multiple select2 Select field.
What I want is to add a new value to my select field. (after adding an entry to the database and bind this entry to the select field)
This is my code so far:
Blade template:
<div class="form-group {{ ($errors->first('projectTypes')) ? 'has-error' : '' }}">
<label for="projectTypes" class="col-md-2 control-label">{{ trans('project/project.fields.projectTypes') }}</label>
<div class="col-md-9">
{!! Form::select('projectTypes[]',
$projectTypes,
($project->projectTypes()->count() > 0) ? $project->projectTypes->lists('id')->toArray() : (isset($projectType)) ? $projectType->id : '',
['id' => 'projectTypes', 'class' => 'form-control', 'ng-model' => 'projectTypes', 'multiple' => 'multiple'])
!!}
<span id="helpBlock" class="help-block">{{ $errors->first('projectTypes') }}</span>
</div>
<div class="col-md-1">
<i class="fa fa-plus-square-o fa-2" data-toggle="modal" data-target="#addProjectType"></i>
</div>
The <i> tag toggles the modal. In the modal window I have an input field and a button (it works!):
<input ng-model="name" id="addProjectType" class="form-control" type="text" name="name" placeholder="Projekttyp">
<button type="button" class="btn btn-primary btn-embossed" ng-click="addProjectType(name)" data-dismiss="modal">Save changes</button>
So if I click on the button this will trigger a function in my angularJS code (this works!).
This is my angularJS Code:
$scope.projectTypes = [];
$scope.addProjectType = function(name) {
$http.post('/ajax/projecttype/addprojecttype', {
name: name
}).success(function(data, status, headers, config) {
$scope.projectTypes.push(data);
});
}
This do an ajax call to my laravel php function (this works!):
public function addProjectType(Request $request, Sentinel $sentinel) {
$name = $request->get('name');
$projectType = new ProjectType;
$projectType->name = $name;
$projectType->slug = $projectType->strSlug($name);
$this->created_by = $sentinel::getUser()->id;
$this->updated_by = $sentinel::getUser()->id;
$projectType->saveModel($request);
return Response::json($projectType, self::$OK);
}
But although I have declared my select field (ng-model="projectTypes")
and I declared the $scope.projectTypes and push the new Object to the $scope.projectTypes after the ajax call the select field won't update.
What am I doing wrong here?

Categories