JS Script crashes after temporaryURL is created with livewire - javascript

Does anyone know, How to resolve this issue of the crashed javascript script?
I am using 2 checkboxes to load some DOM.
1st checkbox is to expand textarea with the CKEditor script which is loaded with the JS but I have a wire model to send data to the controller.
Here is HTML for 1st checkbox:
<div class="form-group mt-25 d-flex flex-row">
<label class="checkbox-container form-group__label">
{{ __('Extended description') }}
<input type="checkbox" name="extended-description-checkbox" id="extended-description-checkbox" class="checkbox">
<span class="checkmark"></span>
</label>
</div>
<div class="form-group mt-25 cke d-none" id="extended-description-checkbox-div">
<label class="form-group__label" for="extended-description">{{ __('Extended description') }}</label>
<textarea wire:ignore.self wire:model.debounce.250ms.defer="extendedDescription" name="extended-description" id="extended-description" cols="30" rows="10"></textarea>
</div>
2nd checkbox is also handled with the JS and has a temporary URL method since the expanded DOM element should contain uploaded images for the gallery.
Here is HTML of the 2nd checkbox:
<div class="form-group mt-25 d-flex flex-row">
<label class="checkbox-container form-group__label">
{{ __('Use default images') }}
<input type="checkbox" name="use-default-images" id="use-default-images" class="checkbox">
<span class="checkmark"></span>
</label>
</div>
<div class="d-none" id="use-default-images-div">
<div class="form-group mt-25">
<label class="form-group__label">{{ __('Service images') }}</label>
<div class="form-group__uploaded-images">
#if ($additionalImages)
#foreach($additionalImages as $image)
<img src="{{ $image->temporaryUrl() }}" alt="Temporary image">
#endforeach
#endif
</div>
</div>
<div class="custom-file ml-auto">
<button type="button" class="ml-auto styled-link">{{ __('Add images') }}</button>
<div class="row mt-25">
<div class="col-4 col-md-8"></div>
<div class="col-8 col-md-4">
<input wire:ignore.self wire:model.defer="additionalImages" type="file" multiple>
#error('images.*') {{ $message }} #enderror
</div>
</div>
</div>
</div>
Here are the scripts for expanding of the both DOM elements:
const extendedCheckbox = document.querySelector('#extended-description-checkbox');
const extendedDiv = document.querySelector('#extended-description-checkbox-div');
extendedCheckbox.addEventListener('change', function() {
if(extendedCheckbox.checked) {
extendedDiv.classList.remove('d-none');
} else {
extendedDiv.classList.add('d-none');
}
});
const defaultImagesCheckbox = document.querySelector('#use-default-images');
const defaultImagesDiv = document.querySelector('#use-default-images-div');
defaultImagesCheckbox.addEventListener('change', function() {
if(defaultImagesCheckbox.checked) {
defaultImagesDiv.classList.remove('d-none');
} else {
defaultImagesDiv.classList.add('d-none');
}
});

Related

Display JSON Array in laravel blade

I need to display the JSON data which is inside the column extras_name individually inside a input boxes with the value filled on edit
Here's the blade file codes
<div class="card">
<h5 class="card-header">
Manage Extras
</h5>
<div class="card-body">
{{ $customProduct }}
<br><br><br>
<div class="optionBox">
<div class="block main">
<div class="form-row pb-2">
<div class="col">
<input type="text" class="form-control" name="extras_name[]" value="{{ $customProduct->name }}" placeholder="Name">
</div>
<div class="col">
<input type="text" class="form-control" name="extras_price[]" placeholder="Price">
</div>
<div class="col">
<button type="button" class="remove btn btn-danger"><i class="fas fa-trash-alt"></i></button>
</div>
</div>
<div class="block mt-2 ">
<button type="button" class="add btn btn-success">Add Extras</i></button>
</div>
</div>
</div>
</div>
</div>
Here's the Controller Edit function
public function edit($venue, CustomProduct $customProduct)
{
$data = [
'customProduct'=>$customProduct,
];
return view('manage.custom-products.edit')->with($data);
}
Here's how the data is saved in the database
If you want to show data in a table then you can use this code
<td>
#foreach(json_decode($value->extras_name, true) as $extras_name)
{{ $extras_name}}
#endforeach
</td>
first of all json_decode this
and then in foreach you can use that.
Blade File:
#if(!empty(json_decode($data->extras_name))) {{--JUST FOR CHEKING THAT IF THIS WAS NOT JSON OR THIS WAS NULL, THE ERROR NOT SHOWING--}}
#foreach(json_decode($data->extras_name as $title=>$value))
<label>
{{$title ?? ''}} : {{$value ?? ''}}
</label>
<br/>
#endforeach
#endif
it doesnt make sense to do that
instead you can show your values on list item below your input and when new value is added or removed refresh the list using ajax

Laravel Edit Update JSON Array and remove specific input using JavaScript

How can i load the JSON array saved in the database to the edit form input field ?
Here's how my create form looks like
Here's the form Code
<div class="card">
<h5 class="card-header">
Manage Extras
</h5>
<div class="card-body">
<div class="optionBox">
<div class="block main">
<div class="form-row pb-2">
<div class="col">
<input type="text" class="form-control" name="extras_name[]" value="" placeholder="Name">
</div>
<div class="col">
<input type="text" class="form-control" name="extras_price[]" placeholder="Price">
</div>
<div class="col">
<button type="button" class="remove btn btn-danger"><i class="fas fa-trash-alt"></i></button>
</div>
</div>
<div class="block mt-2 ">
<button type="button" class="add btn btn-success">Add Extras</i></button>
</div>
</div>
</div>
</div>
</div>
Here's the Script to Add Extra input field and delete button
<script>
$('.add').click(function() {
$('.block:last').before('<div class="form-row pb-2"><div class="col"><input type="text" class="form-control" name="extras_name[]" placeholder="Name"></div><div class="col"><input type="text" class="form-control" name="extras_price[]" placeholder="Price"></div><div class="col"><button type="button" class="remove btn btn-danger"><i class="fas fa-trash-alt"></i></button></div></div>');
});
$('.optionBox').on('click','.remove',function() {
$(this).parent().parent().remove();
});
</script>
Here's how it saves in the database
Here's the edit function in the Controller
public function edit(CustomProduct $customProduct)
{
$data = [
'customProduct'=>$customProduct,
];
return view('manage.custom-products.edit')->with($data);
}
I was able to load the data into the form using a foreach as below
<div class="row">
<div class="col">
<strong>Names</strong>
#foreach ($customProduct['extras_name'] as $item)
<li>{{ $item }}</li>
#endforeach
</div>
<div class="col">
<strong>Prices</strong>
#foreach ($customProduct['extras_price'] as $item)
<li>{{ $item }}</li>
#endforeach
</div>
</div>
And here's how it was looking like
I just want to load the json data into the input fields on edit and should be able to remove a pacific input by clicking the delete icon,
How can i do make this happen, Please help me out

Passing data using array from View (Blade) to Controller in laravel

I have a blade form which has a repeater input box and a select box, the repeater works fine but how do i pass the data from those fields to back-end controller in laravel?
add.balde.php
<!--begin::Add-Invoice-Form-->
<form class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" action="{{route('store_invoice')}}" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="m-portlet__body">
<div class="form-group m-form__group row">
<div class="col-lg-4">
<label>
Customer Name:
</label>
<select class="form-control m-select2" id="m_select2_1" name="customerId">
#foreach($customer_list as $customer)
<option value=" {{ $customer->id }} ">
{{ $customer->fName }} {{ $customer->mName }} {{ $customer->lName }}
</option>
#endforeach
</select>
</div>
<div class="col-lg-4">
<label>
Invoice Type:
</label>
<div class="m-radio-inline">
<label class="m-radio m-radio--solid">
<input type="radio" name="invoiceType" checked value="billable">
Billable
<span></span>
</label>
<label class="m-radio m-radio--solid">
<input type="radio" name="invoiceType" value="nonbillable">
Non Billable
<span></span>
</label>
</div>
</div>
</div>
<div id="m_repeater_1">
<div class="form-group row" id="m_repeater_1">
<div data-repeater-list="" class="col-lg-12">
<div data-repeater-item class="form-group m-form__group row align-items-center">
<div class="col-lg-4">
<label>
Summary Number:
</label>
<select class="form-control m-select2" id="m_select2_2" name="certificateId[]">
#foreach($certificate_list as $certificate)
<option value=" {{ $certificate->id }} ">
{{ $certificate->summary_no }} ( {{ $certificate->certificateType() }} )
</option>
#endforeach
</select>
</div>
<div class="col-lg-3">
<label>
Rate:
</label>
<input type="number" class="form-control m-input" name="rate" placeholder="Enter rate">
</div>
<div class="col-lg-3">
<br/>
<div data-repeater-delete="" class="btn btn btn-danger m-btn m-btn--icon">
<span>
<i class="la la-trash-o"></i>
<span>
Remove
</span>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="m-form__group form-group row">
<div class="col-lg-4">
<div data-repeater-create="" class="btn btn btn-warning m-btn m-btn--icon">
<span>
<i class="la la-plus"></i>
<span>
Add
</span>
</span>
</div>
</div>
</div></div>
</div>
<div class="m-portlet__foot m-portlet__no-border m-portlet__foot--fit">
<div class="m-form__actions m-form__actions--solid">
<div class="row">
<div class="col-lg-4"></div>
<div class="col-lg-8">
<button type="submit" class="btn btn-primary">
Submit
</button>
<button type="reset" class="btn btn-secondary">
Cancel
</button>
</div>
</div>
</div>
</div>
</form>
<!--end::Add-Invoice-Form-->
How do I send the values in array format when multiple select box have been filed using repeater?This images shows the UI for the form
Thank you
you can try something like this
<input type="text" value="val" name="somename[]">
<select name="someSelectName[]">
<option value="value">select 1
</option>
</select>
on server side you will receive selected values as array with given name
Change your
<div data-repeater-list="" class="col-lg-12">
To
<div data-repeater-list="arrayName" class="col-lg-12">
and It should work.
This makes the all the input names to have an array format of arrayName[number][input] and the number increments for each input and finally in the request sent you will have all the inputs in the arrayName

this.validator is not a function with formarray. Angular2

I'm working on a page which has a nested Formarray.
constructor(private fb: FormBuilder) {
this.buildForm();
}
private buildForm() {
this.trialBudgetForm = this.fb.group({
clients: this.fb.array([])
})
}
addCustomer() {
this.clients.push(this.initCustomer());
}
initCustomer() {
return this.fb.group({
earnedIncomes: this.fb.array([this.initIncome()]),
thirtyAndOneThirdYN: [],
thirtyYN: [],
earnedIncomeExpenseType: [],
earnedIncomeExpense: [],
dependentCareExpense: []
})
}
initIncome() {
return this.fb.group(new ScrAmountType());
}
ngOnInit() {
this.populateData();
}
populateData() {
const clients = this.TrialBudgetData.clients;
const customerFGs = clients.map(customer => this.fb.group({
earnedIncomes: this.populateIncome(customer.earnedIncomes),
thirtyAndOneThirdYN: [this.utilService.YNConvert(customer.thirtyAndOneThirdYN)],
thirtyYN: [this.utilService.YNConvert(customer.thirtyYN)],
earnedIncomeExpenseType: [customer.earnedIncomeExpenseType],
earnedIncomeExpense: [customer.earnedIncomeExpense],
dependentCareExpense: [customer.dependentCareExpense]
}));
const customerFormArray = this.fb.array(customerFGs);
this.trialBudgetForm.setControl('clients', customerFormArray);
}
for demo purpose, i didn't post the entire ts file, coz there are almost 600 lines. But i can provide more detail if needed.
here's the html page (also only a snippet)
<form novalidate [formGroup]="trialBudgetForm" (ngSubmit)="save(trialBudgetForm)">
<div class="settingsPage-box">
<h3 class="box-border-bottom">Earned Income
<span class="float_right add-field add-margin hand" (click)="addCustomer()">
<i class=" fa fa-plus-circle fa-lg plusIconColor"></i>
<span>
Add Earned Income
</span>
</span>
</h3>
<div formArrayName="clients">
<div *ngFor="let earnedIncomeCustomer of clients.controls; let i = index" [formGroupName]="i" class="row-view box-border-bottom">
<div class="box-border-bottom row-view">
<div class="col-sm-3 padding0">
<label for="customer{{i+1}}" class="pushDown">Customer {{i+1}}:</label>
</div>
<div class="col-sm-9 grid-block padding0">
<div class="col-sm-1 float_right" (click)="deleteCustomer(i)">
<span class="delete-row hand">
<i class="fa fa-trash-o"></i>
</span>
</div>
</div>
<div class="col-sm-3">
<label class="pushDown">Earned Income</label>
</div>
<div class="col-sm-9 grid-block">
<div class="row">
<div class="col-sm-6 u-justifyEnd">
<span class="add-margin float-left hand" (click)="addEarnedIncome(i)"><i class=" fa fa-plus-circle fa-lg plusIconColor"></i><span> Add Income</span></span>
</div>
</div>
<div class="row grid-block pd-left amount-grid" formArrayName="earnedIncomes" >
<div class="row-view" *ngFor="let earnedIncome of earnedIncomeCustomer.controls.earnedIncomes.controls; let j = index"
[formGroupName]="j">
<div class="col-sm-5 padding5">
<span class="label-type" *ngIf="j==0">Type</span>
<select class="form-control" formControlName="type" (change)="checkForDuplicateEarnedIncomeType(this.trialBudgetForm.controls.clients.controls[i].controls.earnedIncomes.controls[j].value.type)">
<option value="">Select</option>
<option *ngFor="let optionEntity of this.constantsService.getDropDownFromLookup(this.constantsService.getText('EarningType'))"
value="{{optionEntity.lookupBean.code}}">{{optionEntity.lookupBean.longLabel}}</option>
</select>
</div>
<div class="col-sm-6 pd-left padding5 amount-bg">
<span class="label-type" *ngIf="j==0">Amount</span>
<div class="search-container">
<input (keypress)="this.customValidatorsService.validateNumberOnly($event)" formControlName="amount" class="form-control amount-input search-box"
placeholder="$0.00" currencyMask [options]="{ allowNegative: false,prefix: '$',hundreds: ',' }" maxlength="12"
(keyup)="calculateTotalIncome(earnedIncomeCustomer, i)" />
</div>
<div class="clearfix"></div>
</div>
<div class="col-sm-1 pd-left">
<span class="label-type" *ngIf="j==0"> </span>
<span class="delete-row hand" (click)="deleteIncome(earnedIncomeCustomer, i, j)"> <!-- G.S Income.controls.amount -->
<i class="fa fa-trash-o"></i>
</span>
</div>
</div>
<div class="row-view">
<div class="col-sm-5">
<span class="total-info text-right">Total Earned Income</span>
</div>
<div class="col-sm-6 pd-left amount-bg">
<span class="total-info text-right">${{ earnedIncomeCustomer.totalEarnedIncome | number : '1.2-2'}}
</span>
<div class="clearfix"></div>
</div>
</div>
<div class="row-view">
<div class="col-sm-12 text-center">
<div class="clearfix"></div>
</div>
</div>
</div>
<span *ngIf="duplicateEarnedIncomeType" class="red-font-color">Choose a different use type</span>
</div>
<div class="clearfix"></div>
</div>
<div class="box-border-bottom row-view">
<div class="col-sm-3">
<label class="pushDown">Earned Income Options</label>
</div>
<div class="col-sm-8 grid-block">
<div class="col-sm-5 form-group label-check display-check">
<input type="checkbox" id="check-1" formControlName="thirtyAndOneThirdYN">
<label for="check-1">30+1/3</label>
</div>
<div class="col-sm-6 form-group label-check display-check">
<input type="checkbox" id="check-2" formControlName="thirtyYN">
<label for="check-2">$30</label>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="box-border-bottom row-view">
<div class="col-sm-3">
<label class="pushDown">Earned Income Expenses</label>
</div>
<div class="col-sm-8 grid-block">
<div class="col-sm-5 form-group padding_right">
<div class="control-label">Type</div>
<select class="form-control" formControlName="earnedIncomeExpenseType">
<option value="-1">Select</option>
<option *ngFor="let optionEntity of this.constantsService.getDropDownFromLookup(this.constantsService.getText('EIexpenseType'))"
value="{{optionEntity.lookupBean.code}}">{{optionEntity.lookupBean.longLabel}}</option>
</select>
</div>
<div class="col-sm-6 padding0 padding_custom">
<div class="control-label">Amount</div>
<input formControlName="earnedIncomeExpense" currencyMask (keypress)="numberOnly($event)" class="form-control" [options]="{ allowNegative: false, prefix: '$',hundreds: ',' }"
placeholder="$0.00" maxlength="10" />
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="row-view">
<div class="col-sm-3">
<label class="pushDown">Dependent Care Expenses</label>
</div>
<div class="col-sm-8 grid-block">
<div class="col-sm-5">
<div class="control-label">Expenses</div>
<input (keypress)="numberOnly($event)" currencyMask formControlName="dependentCareExpense" class="form-control" maxlength="10"
placeholder="$0.00" [options]="{ allowNegative: false, prefix: '$',hundreds: ',' }" />
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</form>
I have been trying to debug this for couple days now. The issue happens after constructor executed and before ngOnInit was called. this error only occur when I added more than one customer, and come back to this page. (adding customer won't cause any problem, only when I comeback to this page that's when the error this.validator is not a function is shown.
It's strange because the error happen between constructor and ngOnInit, and populateData is called in ngOnInit, which means error occured before the page know how many customers will I load. But if only the error occur because I add more than one customer, it seems that applicaiton has to get that info within constructor, in which i didn't load the data yet.
Update 1: Sept 25 3:39PM EST
updated with populateData function
Update 2: full stack error: Sept 25 4:09PM EST
TrialBudgetComponent_Host.html:1 ERROR TypeError: this.validator is not a function
at FormControl.webpackJsonp.../../../forms/#angular/forms.es5.js.AbstractControl._runValidator (forms.es5.js:2645)
at FormControl.webpackJsonp.../../../forms/#angular/forms.es5.js.AbstractControl.updateValueAndValidity (forms.es5.js:2613)
at new FormControl (forms.es5.js:2936)
at FormBuilder.webpackJsonp.../../../forms/#angular/forms.es5.js.FormBuilder.control (forms.es5.js:5780)
at FormBuilder.webpackJsonp.../../../forms/#angular/forms.es5.js.FormBuilder._createControl (forms.es5.js:5822)
at forms.es5.js:5804
at Array.forEach (<anonymous>)
at FormBuilder.webpackJsonp.../../../forms/#angular/forms.es5.js.FormBuilder._reduceControls (forms.es5.js:5803)
at FormBuilder.webpackJsonp.../../../forms/#angular/forms.es5.js.FormBuilder.group (forms.es5.js:5762)
at TrialBudgetComponent.webpackJsonp.../../../../../src/app/trial-budget/trial-budget.component.ts.TrialBudgetComponent.toFromGroup (trial-budget.component.ts:102)
Update 3 question closed: thanks to #yurzui's comment
I just realized that the architecture is messed up for this page. This component has a parent which only has (current component selector) in its template. The two component has exactly the same name just under different folder. The parent is at /trial-budget and children is at /trial-budget/trial-budget-main. The TrialBudgetComponent.toFromGroup is actually a function inside the parent. For some reason, it's being called inside ngInit instead of constructor. Still haven't figure out why error only happen with 2 customer.
But lesson learned:
1. read error message carefully especially first and last couple lines. I didn't read the last line.
2. always construct form inside constructor and populate data inside ngOnInit()

Angular JS Multiple ngRepeat

I'm trying to do the following : When you click on "Add Package" its pushes to an array a package where I can specify e.g. Package one, but within that I want to push multiple items (products) "Add Item". The problem is when I create a new package it works, but the items in each package is the same so when I add more to either dynamic package the items within is the same. I assume that's because the array is the same each time, how to I track that by index?
HTML:
<div class="col-12 order-box" ng-repeat="orderpackage in orderproductspackages track by $index">
<div class="col-12">
<label for="name_{{$index}}">Package Name</label>
<input type="text" ng-model="orderpackage.orderpackagename" name="name_{{$index}}" required>
</div>
<div class="col-12" ng-repeat="ordercontent in orderproductscontents track by $index">
<div class="col-2">
<label for="name_{{$index}}">Product</label>
<select ng-model="ordercontent.ordercontentname" name="name_{{$index}}" ng-change="onProductChange(ordercontent.ordercontentname,$index)">
<option ng-repeat="product in productResponse | orderBy:'productname'" value="{{product.productname}}">{{product.productname}}</option>
</select>
</div>
<div class="col-2">
<label for="name_{{$index}}">Quantity</label>
<input type="text" ng-model="ordercontent.ordercontentquantity" name="name_{{$index}}" ng-keyup="onProductChange(ordercontent.ordercontentname,$index)" required>
</div>
<div class="col-2">
<label for="name_{{$index}}">Price</label>
<input type="text" ng-model="ordercontent.ordercontentprice" name="name_{{$index}}" ng-change="onPriceChange(ordercontent.ordercontentname,$index)" disabled required>
</div>
<div class="col-2">
<label for="name_{{$index}}">Per {{ordercontent.ordercontentmeasurement}}</label>
<input type="text" ng-model="ordercontent.ordercontentpriceper" name="name_{{$index}}" disabled required>
</div>
<div class="col-2">
<label for="name_{{$index}}">Total</label>
<input type="text" ng-model="ordercontent.ordercontenttotal" name="name_{{$index}}" required disabled>
</div>
<div class="col-2">
<label for="name_{{$index}}">Options</label>
<a class="button critical small" ng-click="removeOrderContent($index)"><span class="fa fa-minus"></span> Remove</a>
</div>
</div>
<div class="col-12 m20-top p15 text-center add-api" ng-click="addOrderContent()">
<span class="fa fa-plus"></span> Add Item</a>
</div>
</div>
<div class="col-12 m20-top p15 text-center add-api" ng-click="addOrderPackage()">
<span class="fa fa-plus"></span> Add Package</a>
</div>
CODE SNIPPETS :
_this.addOrderPackage = function() {
_this.orderproductspackages.push({ ordernumber:_this.order.ordernumber });
}
_this.addOrderContent = function() {
_this.orderproductscontents.push({
ordercontentname:'',
ordercontentquantity:'1',
ordercontentprice:'',
ordercontentpriceper:'',
ordercontenttotal:''
});
}
Of course, all items in your packages are the same, because you use the same content array inside packages: ng-repeat="ordercontent in orderproductscontents". If I understand you right, you need this array orderproductscontents to be distinctive in each package. To do this store this array in package object, like this:
_this.addOrderPackage = function() {
_this.orderproductspackages.push({
ordernumber: _this.order.ordernumber,
contents: []
});
}
and then just ng-repeat="ordercontent in orderpackage. contents"

Categories

Resources