In the case of having many products, and user can dynamically adding new dropdown box. When I click submit, I want to get the value of "category[]" within the form only.
and this is the code:
<form name="store_category" method="post" enctype="multipart/form-data" action="{{ route('admin.product.category.store') }}">
{!!csrf_field()!!}
{!!""; $lang = session('locale') == "" ? "zh" : session('locale'); !!}
<div class="form-group category-select-container">
{!! Form::select("categories_$project->id[]", ${"categories_" . $lang}, null, ["class" => "input-sm"]) !!}
{{trans('string.Remove')}}
</div>
<div class="form-group">
<button type="button" class="btn btn-dark btn-add-more-category">{{trans('string.Add More')}}</button>
<button type="submit" class="btn blue btn-theme-colored">{{trans('string.submit')}}</button>
</div>
</form>
I've tried to rename the array name to something else, but when the user dynamically adding new dropdown box, it couldn't follow the number of the project for the row.
var template = '<div class="form-group category-select-container">'+
'{!! Form::select("categories_$project->id[]", ${"categories_" . $lang}, null, ["class" => "input-sm"]) !!}'+
'{{trans("string.Remove")}}'+
'</div>';
$('.btn-add-more-category').on('click', function(e){
e.preventDefault();
$(this).before(template);
})
I really would like to know what could be the output of this line in your Form::select()s
categories_$project->id[]
So anyway, if you would like to group your select tags you have to assign each of them with the same name. Suppose you are looping in an array of $projects. Each row would have
<form name="store_category" method="post" enctype="multipart/form-data" action="{{ route('admin.product.category.store') }}">
{!!csrf_field()!!}
#php $lang = session('locale') == "" ? "zh" : session('locale'); #endphp
<div class="form-group category-select-container">
{!! Form::select("category[]", ${"categories_" . $lang}, null, ["class" => "input-sm"]) !!}
{{trans('string.Remove')}}
</div>
<div class="form-group">
<button type="button" class="btn btn-dark btn-add-more-category">{{trans('string.Add More')}}</button>
<button type="submit" class="btn blue btn-theme-colored">{{trans('string.submit')}}</button>
</div>
</form>
Then next, you have to bind a click event to all your .btn-add-more-category. Let's say your parent table has a class of .table
<script>
$(function () {
$(".table").on("click", ".btn-add-more-category", function(e) {
var template = '<div class="form-group category-select-container"> ' +
'{!! Form::select("category[]", ${"categories_" . $lang}, null, ["class" => "input-sm"]) !!} ' +
'{{trans('string.Remove')}}' +
'</div>';
var container = $(this).parent();
$(template).insertBefore(container);
});
});
</script>
Also, I suggest that you move this line to your controller
$lang = session('locale') == "" ? "zh" : session('locale');
Related
So, I am trying to use jQuery Validate to check for duplicate values in a form, and it's working for the most part. However, I am getting the following weird behavior:
The user will enter a couple duplicate values, and click save
jQuery Validate will show 'Duplicate Name' in the UI for each of the duplicate values
The user does not fix the duplicate values, but rather, adds another duplicate value
The user clicks save again, and the previous two invalid elements are marked valid, and the Duplicate Name message disappears, but the third value is correctly marked as invalid.
If the user clicks save again, then all three error messages are shown correctly.
If the user clicks on save without correcting any, the client-side validation is not followed and the server-side errors are shown for duplicate values.
Basically, I'm wondering what is wrong with my jQuery validation logic? Is it that I'm not forcing a revalidation every time the save button is clicked?
Here is my jQuery Validation code:
$.validator.addMethod("checkForDuplicateClaimName", function (value, element) {
console.log('calling checkDuplicateClaimName')
var customClaimForm = $("form.form-horizontal");
var claimRepeated = 0;
if (value != '') {
var matchingClaims = 0;
// Loop through the whole form to find duplicate claim names
customClaimForm.children().each(function (count, item) {
// Have to iterate through the custom claim div to find the names
if ($(item).attr("id") === "custom-claims-div") {
var customClaimDiv = $("#custom-claims-div");
customClaimDiv.children().each(function (count, claim) {
var customClaimNameToCompare = $(claim).find('label').text();
if (value == customClaimNameToCompare) {
matchingClaims++;
}
});
}
// Not the custom claim div, just the labels from the default scopes
else {
var nameToCompare = $(item).find('label').text();
if ((value == nameToCompare)) {
matchingClaims++;
}
}
});
}
return matchingClaims === 1 || matchingClaims === 0;
}, "Duplicate Name");
$.validator.addClassRules("duplicateClaimName", {
checkForDuplicateClaimName: true
});
var validate = $("form.form-horizontal").validate({
ignore: "", // This checks hidden input values, which is what we want for the claim name validation
errorElement: 'div',
errorClass: 'custom-claim-validation-error',
errorPlacement: function (error, element) {
error.appendTo($(element).parent().find("#claim-name-lbl"))
},
submitHandler: function (form) {
console.log('calling submit handler');
form.submit();
}
});
$('form.form-horizontal').submit(function () {
console.log('calling submit form');
console.log(validate);
});
Here is the code for when a new claim is added to the custom-claims-div. It is the code that adds the class duplicateClaimName for jquery validation.
function oidc_addCustomProfileClaim() {
// Grab the custom claim name and value
var customAttName = $("#dialog-add-custom-scope-claim #customAttName").val();
var customAttValue = $("#dialog-add-custom-scope-claim #customAttValue").val();
// Get the last index of the custom claim div
var lastId: number = -1;
var div = $("#custom-claims-div");
if ($("#custom-claims-div").children().length) {
lastId = parseInt($("#custom-claims-div").children().last().attr("data-id"), 10);
}
lastId++;
// Create the new form-group
var newDiv = $("<div data-id=\"" + lastId + "\" id=\"claim-info-div\" class=\"form-group row\">");
newDiv.append("<label data-id=\"" + lastId + "\" id=\"claim-name-lbl\" name=\"CustomClaims[" + lastId + "].ClaimLabel\" class=\"col-sm-2 control-label no-padding-right\" style=\"padding-right: 10px! important;\" value=\"" + customAttName + "\">" + customAttName + "</label>");
//Need to make a hidden input so that the model will be correctly filled when passed to the controller
newDiv.append("<input data-id=\"" + lastId + "\" id=\"claim-value\" name=\"CustomClaims[" + lastId + "].ClaimValue\" type=\"text\" class=\"col-md-5\" value=\"" + customAttValue + "\" />")
newDiv.append("<input id=\"hidden-claim-value\" name=\"CustomClaims[" + lastId + "].ClaimLabel\" class=\"duplicateClaimName\" type=\"hidden\" value=\"" + customAttName + "\" />")
// Create the label for disabling/enabling the claim
newDiv.append("<input data-id=\"" + lastId + "\" id=\"disable-claim-chkbx\" name=\"CustomClaims[" + lastId + "].IsDisabled\" style=\"margin-left: 75px;\" type=\"checkbox\" value=\"false\"/>");
// Create the Button
var button = $("<button class=\"btn btn-xs btn-white btn-danger\" data-action=\"delete\" style=\"margin-left: 79px; width=80px;\" type=\"button\">");
var deleteText = $("<i class=\"ace-icon fa fa-trash-o fa-lg\">");
// Build the form group
button.append(deleteText);
button.append(" Delete");
newDiv.append(button);
div.append(newDiv);
}
This is the modal JS to add a new claim to the form:
$("#dialog-add-custom-scope-claim").dialog({
autoOpen: false,
resizable: false,
modal: true,
width: 420,
title: "<div class=\"widget-header\">Add a new profile custom scope</div>",
title_html: true,
buttons: [
{
text: "Add",
"class": "btn btn-primary btn-xs no-border",
click: function () {
oidc_addCustomProfileClaim();
$('#new-claim-name-form').find('#customAttName').val('');
$('#new-claim-value-form').find('#customAttValue').val('');
$(this).dialog("close");
}
},
{
text: "Cancel",
"class": "btn btn-xs no-border",
click: function () {
$('#new-claim-name-form').find('#customAttName').val('');
$('#new-claim-value-form').find('#customAttValue').val('');
$(this).dialog("close");
}
}
]
});
The elements in question have the correct duplicateClaimName class in the HTML:
<input id="hidden-claim-value" name="CustomClaims[#i].ClaimLabel" type="hidden" class="duplicateClaimName" value="#Model.CustomClaims[i].ClaimLabel" />
Thanks in advance for any input!
Edit:
Here is the relevant HTML for my form submit button, if it helps:
#using (Html.BeginFormWithCss("form-horizontal"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Please, fix the following errors.", new { #class = "alert alert-block alert-danger no-style-list" })
<h3 class="header smaller lighter green">Scope profile</h3>
<div class="form-group">
<label class="col-sm-2 control-label no-padding-right">Name</label>
<div class="col-sm-10">
<input id="Name" name="Name" type="text" data-auto="attributes" class="col-xs-12 col-md-4" value="#Model.Name" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label no-padding-right">FamilyName</label>
<div class="col-sm-10">
<input id="FamilyName" name="FamilyName" type="text" data-auto="attributes" class="col-xs-12 col-md-4" value="#Model.FamilyName" />
</div>
</div>
<div id="custom-claims-div" class="form-group">
#if (#Model.CustomClaims.Count() > 0)
{
for (int i = 0; i < #Model.CustomClaims.Count(); i++)
{
<div data-id="#i" id="claim-info-div" class="form-group row">
<label data-id="#i" id="claim-name-lbl" name="CustomClaims[#i].ClaimLabel" class="col-sm-2 control-label no-padding-right" style="padding-right: 10px !important;" value="#Model.CustomClaims[i].ClaimLabel">#Model.CustomClaims[i].ClaimLabel</label>
<input data-id="#i" id="claim-value" name="CustomClaims[#i].ClaimValue" type="text" data-auto="attributes" class="col-md-5" value="#Model.CustomClaims[i].ClaimValue" />
<input id="hidden-claim-value" name="CustomClaims[#i].ClaimLabel" type="hidden" value="#Model.CustomClaims[i].ClaimLabel" />
#if (Model.CustomClaims[i].IsDisabled)
{
<input data-id="#i" id="disable-claim-chkbx" name="CustomClaims[#i].IsDisabled" style="margin-left: 75px;" type="checkbox" checked="checked" value="true" />
}
else
{
<input data-id="#i" id="disable-claim-chkbx" name="CustomClaims[#i].IsDisabled" style="margin-left: 75px;" type="checkbox" value="false" />
}
<button class="btn btn-xs btn-white btn-danger" data-action="delete" style="margin-left: 75px;" type="button">
<i class="ace-icon fa fa-trash-o fa-lg"></i>
Delete
</button>
</div>
}
}
</div>
<div id="dialog-add-custom-scope-claim" class=modal>
<div>
<div id="new-claim-name-form" class="form-group">
<label class="control-label">Claim Name</label>
<input id="customAttName" style="margin-bottom: 10px" type="text" value="" class="col-xs-12" placeholder="Claim Name" />
</div>
<div id="new-claim-value-form" class="form-group">
<label class="control-label">Claim Value</label>
<input id="customAttValue" type="text" value="" class="col-xs-12" placeholder="Claim Value (attribute name from FID)" />
</div>
</div>
</div>
<div class="clearfix form-actions">
<div class="col-md-offset-1 col-md-9">
<button class="btn btn-info" type="submit">
<i class="ace-icon fa fa-check fa-lg"></i>
Save
</button>
<a class="btn" href="#Url.Action("Index")">
<i class="ace-icon fa fa-times fa-lg"></i>
Cancel
</a>
</div>
</div>
I am trying not to use formset in my form. Instead of that, I'm trying to create the form dynamically and save all forms data in the DB.
I can create a dynamic form, but whenever I create multiple forms in "create order", it always saves the last forms data. For example, once I create 3 forms, and after saving the form, the table shows me only 3rd form data, which means it does not save all data together.
views.py
def create_order(request):
from django import forms
form = OrderForm()
if request.method == 'POST':
forms = OrderForm(request.POST)
if forms.is_valid():
po_id = forms.cleaned_data['po_id']
supplier = forms.cleaned_data['supplier']
product = forms.cleaned_data['product']
part = forms.cleaned_data['part']
order = Order.objects.create(
po_id=po_id,
supplier=supplier,
product=product,
part=part,
)
forms.save()
return redirect('order-list')
context = {
'form': form
}
return render(request, 'store/addOrder.html', context)
forms.py
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['supplier', 'product', 'part','po_id']
widgets = {
'supplier': forms.Select(attrs={'class': 'form-control', 'id': 'supplier'}),
'product': forms.Select(attrs={'class': 'form-control', 'id': 'product'}),
'part': forms.Select(attrs={'class': 'form-control', 'id': 'part'}),
}
HTML
<form action="#" method="post" id="form-container" novalidate="novalidate">
{% csrf_token %}
<div class="form">
<div class="form-group">
<label for="po_id" class="control-label mb-1">ID</label>
{{ form.po_id }}
</div>
<div class="form-group">
<label for="supplier" class="control-label mb-1">Supplier</label>
{{ form.supplier }}
</div>
<div class="form-group">
<label for="product" class="control-label mb-1">Product</label>
{{ form.product }}
</div>
<div class="form-group">
<label for="part" class="control-label mb-1">Part Name</label>
{{ form.part }}
</div>
</div>
<button id="add-form" type="button">Add Another Order</button>
<div>
<button id="payment-button" type="submit" class="btn btn-lg btn-success btn-block">
<span id="payment-button-amount">Save</span>
</button>
</div>
</form>
<script>
let poForm = document.querySelectorAll(".form")
let container = document.querySelector("#form-container")
let addButton = document.querySelector("#add-form")
let totalForms = document.querySelector("#id_form-TOTAL_FORMS")
let formNum = poForm.length-1
addButton.addEventListener('click', addForm)
function addForm(e){
e.preventDefault()
let newForm = poForm[0].cloneNode(true)
let formRegex = RegExp(`form-(\\d){1}-`,'g')
formNum++
newForm.innerHTML = newForm.innerHTML.replace(formRegex, `form-${formNum}-`)
container.insertBefore(newForm, addButton)
totalForms.setAttribute('value', `${formNum+1}`)
}
</script>
What causes this problem? How can I fix it?
I am using Laravel-5.8 for my project. I want to upload image, and click on submit button to save the image and other text fields into the database.
Controller
public function create()
{
$countries = ConfigCountries::all();
return view('organization.companies.create')->with('countries', $countries);
}
public function store(Request $request)
{
try {
$orgStartDate = Carbon::parse($request->org_start_date);
$arr = [
'organisation_code' => $request->organisation_code,
'organisation_name' => $request->organisation_name,
'website' => $request->website,
'org_decription' => $request->org_description,
'total_employees' => $request->total_employees,
'registration_number' => $request->registration_number,
'org_start_date' => $request->$orgStartDate,
'phone_number' => $request->phone_number,
'secondary_phone' => $request->secondary_phone,
'email' => $request->email,
'secondary_email' => $request->secondary_email,
'address1' => $request->address1,
'address2' => $request->address2,
'country_id' => $request->country_id,
'created_by' => Auth::user()->id,
'created_at' => date("Y-m-d H:i:s"),
'is_active' => 1,
];
if ($request->org_image != "") {
$org_image = time() . '_' . $request->org_image->getClientOriginalName();
$request->org_image->move('storage_files/companies/profile/', $org_image);
$arr['org_image'] = 'storage_files/companies/profile/' . $org_image;
}
$company = OrgCompany::create($arr);
$company->save();
Session::flash('success', 'Company is created successfully');
return redirect()->route('organization.companies.index');
} catch (Exception $exception) {
return back()->withInput()
->withErrors(['unexpected_error' => 'Unexpected error occurred while trying to process your request.']);
}
}
view
<div class="card-body">
<form action="{{ route("organization.companies.store") }}" method="post class="form-horizontal" enctype="multipart/form-data">
{{csrf_field()}}
<div class="text-center">
<input type="image" class="profile-user-img img-fluid img-circle"
src="{{asset('theme/adminlte3/dist/img/company_logo.png')}}"
id="wizardPicturePreview" title="" width="150">
<input type="file" name="picture" id="wizard-picture" class="" hidden>
<h4 class="profile-username text-center">Click On Image to Add Logo</h4>
</div>
<span style="color:blue;"><h4 class="box-title"><b>Contact Information</b></h4></span>
<hr class="m-t-0 m-b-40">
<div class="row">
<div class="col-md-6">
<div class="form-group row">
<label class="control-label text-right col-md-3"> Phone No.</label>
<div class="col-md-9 controls">
<input type="text" name="phone_number" placeholder="Enter Company Phone no. here" class="form-control" value="{{old('phone_number')}}">
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group row">
<label class="control-label text-right col-md-3"> Alternative Phone No.</label>
<div class="col-md-9 controls">
<input type="text" name="secondary_phone" placeholder="Enter Alternative Phone no. here" class="form-control" value="{{old('secondary_phone')}}">
</div>
</div>
</div>
<!--/span-->
</div>
<hr>
<div class="form-actions">
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-offset-3 col-md-9">
<button type="submit" class="btn btn-primary">Add Company</button>
<button type="button" onclick="window.location.href='{{route('organization.companies.index')}}'" class="btn btn-default">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function(){
$("#wizard-picture").change(function(){
readURL(this);
});
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#wizardPicturePreview').attr('src', e.target.result).fadeIn('slow');
}
reader.readAsDataURL(input.files[0]);
} }
$("input[type='image']").click(function() {
$("input[id='wizard-picture']").click();
});
$(".form-control").keypress(function(e) {
if (e.which == 13) {
e.preventDefault();
return false;
}
});
</script>
The issue is that without clicking on the save submit button, when I clicked on image file uploader, it redirects to the index page without uploading the image to the screen.
How do I resolve this?
Thanks
An input type of image is a way to define an image as a submit button, so clicking on the image actually is submitting the form. You can either change the image to a regular <img> tag or change you click handler to prevent the default action like so
$("input[type='image']").click(function(e) {
e.preventDefault();
$("input[id='wizard-picture']").click();
});
Also just a heads up, you have a typo in the line that opens your form. There's no closing quotes after method="POST which is probably why the page is just redirecting on submit
Maybe because the closing quote of method is missing in <form> starting tag
I've setup a view which contains a search form:
<form>
<input type="hidden" id="product_id" value="{{$tour->id}}">
<div class="form-group col-md-4">
<label>Date:</label>
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" class="form-control pull-right" id="start" placeholder="Start Date">
</div>
</div>
<div class="form-group col-md-4">
<label>End:</label>
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" class="form-control pull-right" id="end" placeholder="End Date">
</div>
</div>
<div class="form-group col-md-4" id="dateprice-search">
<label></label>
<button type="submit" class="btn" id="btn-search" >
Search
</button>
</div>
The below is the ajax code to handle the request of the form:
$(document).ready(function() {
$('#dateprice-search').on('click', '#btn-search', function() {
$.ajax({
type: 'post',
url: '/date-price',
data: {
'_token': $('input[name=_token]').val(),
'product_id': $("#product_id").val(),
'start': $("#start").val(),
'end': $("#end").val()
},
success: function(data) {
$('.shadow-z-1').show();
$('.shadow-z-1').append("<tr class='liquid-row><td>" + data.start + "</td><td>"+ data.end + "</td><td>" + data.end + "</td><td><a class='btn-m btn btn-m-success'>Available</a></td></tr>");
}
});
});
});
Route:
Route::post('/date-price','GetPublicController#datePrice')
->name('searchDate');
And finally method in controller to give the results:
public function datePrice(Request $request){
$start = $request->start;
$end = $request->end;
$dates = DatePrice::where('tour_id','=',$request->product_id)
->whereBetween('start', array($request->start, $request->end))
->whereBetween('end', array($request->start, $request->end))
->get();
return response()->json($dates);
}
At first the url looks like this before submitting the form http://localhost:8000/trips/popular/trekking/test and url becomes http://localhost:8000/trips/popular/trekking/test? after clicking the search button. Console section of inspect element shows no error in script. What mistake I had made over here ?
It mean your form submiting to same page due to type="submit"
1) change to type="button"
<button type="button" class="btn" id="btn-search" >
2) Here click event should be for button not to div so change the selector and add e.preventDefault(); in jquery to prevent the default submit .
$('#btn-search').on('click', '#btn-search', function() { e.preventDefault(); });
note :
1st : your action attribute missing so form will be submit same page .
2nd : your method attribute missing so it will take default GET method
You have given button type as submit, either remove it as
<button type="button" class="btn" id="btn-search" >
Search
</button>
or use the jquery preventDeafult() function to prevent the default behavior of submit button i.e form submit in your button click event as
$(document).ready(function() {
$('#dateprice-search').on('click', '#btn-search', function(e) {
e.preventDefault();
//your ajax code
});
});
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?