.netcore client-side validation for different onPost handlers (multiple events) - validation

In my .nercore razor page project I have a number of forms with multiple onPost handlers - different buttons for different events (eg. add / copy / edit / delete)
My problem is - I do not understand how I can differentiate client-side validation depending on the button pressed.
EDIT
Let's assume, I have the following .cshtml which defines two input data fields and two buttons. By pressing one button (Add) the first Field A should be validated, by pressing the second (copy) - another one (Field B):
#page "{id:int}/{modeR:int}"
#model MyProject.Pages.MyProjectDB.AddRecordModel
#{
ViewData["Title"] = "Add Record";
}
<div class="row">
<div class="col-md-7">
<form method="post" enctype="multipart/form-data">
<div class="form-group">
<label asp-for="myClass.FieldA" class="control-label"></label>
<input asp-for="myClass.FieldA" class="form-control" />
<span asp-validation-for="myClass.FieldA" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="myClass.FieldB" class="control-label"></label>
<input asp-for="myClass.FieldB" class="form-control" />
<span asp-validation-for="myClass.FieldB" class="text-danger"></span>
</div>
<div class="form-group">
<button type="submit" value="Add" class="btn btn-success">Add Record)</button>
<button type="submit" value="Copy" class="btn btn-warning">Edit Record</button>
</div>
</form>
</div>
</div>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
at the end of my .cshtml page, but it runs always when onPost is called.
I need to run validation "in groups": for one button set of one fields and ignore others, for another - another set and so on like written above
Is there any way to achieve it without writing custom javascript or do it on server side?..
ANOTHER EDIT
The answer was provided for the case where we have clear separation of input fields / buttons. But how can we handle this if we have two input fields and one button. Validation should NOT be fire if either of them is filled in and should fire if both are null. I understand, this sounds a bit strange, but in my example I have one input field and one dropdown-list. So, either a field should be filled-in or an item should be selected from the list, but for code simplicity let's stay with two input fields (Filed A and Field B, one of them should be filled) and one button:
#page "{id:int}/{modeR:int}"
#model MyProject.Pages.MyProjectDB.AddRecordModel
#{
ViewData["Title"] = "Add Record";
}
<div class="row">
<div class="col-md-7">
<form method="post" enctype="multipart/form-data">
<div class="form-group">
<label asp-for="myClass.FieldA" class="control-label"></label>
<input asp-for="myClass.FieldA" class="form-control" />
<span asp-validation-for="myClass.FieldA" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="myClass.FieldB" class="control-label"></label>
<input asp-for="myClass.FieldB" class="form-control" />
<span asp-validation-for="myClass.FieldB" class="text-danger"></span>
</div>
<div class="form-group">
<button type="submit" value="Add" class="btn btn-success">Add Record)</button>
</div>
</form>
</div>
</div>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Thanks in advance!

By pressing one button (Add) the first Field A should be validated, by pressing the second (copy) - another one (Field B) should be validated
You can try to put them in separate <form> and specify handler method via the asp-page-handler attribute, like below.
<h1>Go Add Handler</h1>
<form method="post">
<div class="form-group">
<label asp-for="myClass.FieldA" class="control-label"></label>
<input asp-for="myClass.FieldA" class="form-control" />
<span asp-validation-for="myClass.FieldA" class="text-danger"></span>
</div>
<div>
<button type="submit" value="Add" class="btn btn-success" asp-page-handler="Add">Add Record</button>
</div>
</form>
<hr />
<h1>Go Copy Handler</h1>
<form id="myform" method="post">
<div class="form-group">
<label asp-for="myClass.FieldB" class="control-label"></label>
<input asp-for="myClass.FieldB" class="form-control" />
<span asp-validation-for="myClass.FieldB" class="text-danger"></span>
</div>
<div>
<button type="submit" value="Copy" class="btn btn-warning" asp-page-handler="Copy">Edit Record</button>
</div>
</form>
#section scripts{
#await Html.PartialAsync("_ValidationScriptsPartial")
}
Test Result

Related

Error in passing the foreign key in the form for editing

I have two tables, one named Client and the other named Projects linked together via a foreign key (this is client_id, which is present in Projects).
Each project has an edit button; when I click to edit a project I have a form with all fields secured to it.
To edit a project I have to pass the client id (client_id) associated with that project.
To do this, I did the following:
ROUTE
Route::get('/project/edit/{project}', [ProjectController::class, 'edit'])->name('project.edit');
CONTROLLER
public function edit(Project $project)
{
$client_id = Project::select('client_id')->where('id',$project->id)->get();
//dd($client_id);
return view('project.edit', compact('project','client_id'));
}
VIEW
<div class="row mt-3">
<div class="col-12 col-md-6 namelabel">
<form action="{{route('project.store')}}" method="post" enctype="multipart/form-data">
#csrf
<div class="mb-3">
<input type="hidden" class="form-control" name="client_id" value="{{$client_id}}" >
</div>
<div class="mb-3">
<label for="name" class="form-label">Project name</label>
<input type="text" class="form-control" name="name" value="{{$project->name}}">
</div>
<div class="mb-3">
<div class="mb-3">
<label for="logo" class="form-label">Insert image</label>
<input type="file" name="logo">
</div>
<div class="mb-3">
<label for="project_start_date" class="form-label">Data init</label>
<input type="date" class="form-control" name="project_start_date" value="{{$project->project_start_date}}">
</div>
<label for="description" class="form-label">Description</label>
<textarea name="description" cols="30" rows="10" class="form-control">{{$project->description}}</textarea>
</div>
<button type="submit" class="btn btn-primary mb-5">Modifica progetto</button>
</form>
</div>
</div>
I get the following error:
Incorrect integer value: '[{"client_id":14}]' for column 'client_id' at row 1
How can I solve this problem?
Thanks to those who will help me
This statement
Project::select('client_id')->where('id',$project->id)->get()
does not return the client_id. It returns an Eloquent Collection of Projects with only the client_id Attribute.
You can chain the pluck function to extract only value and then you can call first to get the value from the collection.
Project::select('client_id')
->where('id',$project->id)
->get()
->pluck('client_id')
->first()
After checking your code in the full detail you don't need to do the select part at all.
You have already the Project Model so you can access all of it's fields directly.
$project->client_id
In your view you are doing this already with the name of the project:
{{$project->name}}
You can do the same with the client_id as well:
{{$project->client_id}}

How can I hide and display part of the form on a condition?

I want to use the same form to perform two different operations, and hide and display part of the form on a condition. Let's say if the text of the submit button is "SAVE" admissionNumber input field will not display but if the button text of the submit button is "UPDATE" admissionNumber input field will display. Below is the code sample
registerForm.html the same for being used to register and update student information
<div layout:fragment="content" class="container mySpace">
<form method="post" th:object="${student}" th:action="#{/register}">
<div class="card cardspace">
<h5 class="card-header" th:text="${chead}"></h5>
<div class="card card-body">
<div class="form-row">
<div class="col-9">
<div class="row">
i want to be able hide admissionNumber field if the btname is save and display it if the btname changes to update
<div class="form-group col" th:if="${btnname} == 'Submit'">
<label for="admissionNumber">Admission Number</label> <input
type="text" class="form-control" id="admissionNumber"
th:field="*{admissionNumber}">
<div class="text text-danger"
th:if="${#fields.hasErrors('admissionNumber')}"
th:errors="*{admissionNumber}"></div>
</div>
<div class="form-group col" th:unless="${btnname} == 'Update'">
<label for="admissionNumber">Admission Number</label> <input
type="text" class="form-control" id="admissionNumber"
th:field="*{admissionNumber}">
<div class="text text-danger"
th:if="${#fields.hasErrors('admissionNumber')}"
th:errors="*{admissionNumber}"></div>
</div>
<div class="form-group col">
<label for="firstName">First Name</label> <input type="text"
class="form-control" id="firstName" th:field="*{firstName}">
<div class="text text-danger"
th:if="${#fields.hasErrors('firstName')}"
th:errors="*{firstName}"></div>
</div>
<div class="form-group col">
<label for="lastName">Last Name</label> <input type="text"
class="form-control" id="lastName" th:field="*{lastName}">
<div class="text text-danger"
th:if="${#fields.hasErrors('lastName')}"
th:errors="*{lastName}"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary" th:text="${btnname}"></button>
</form>
student controller class
#Controller
public class StudentController {
#Autowired
private StudentServices studentServices;
displays the registration form
#GetMapping("/register")
public String showStudentRegistrationForm(Model model ) {
model.addAttribute("student", new Student());
model.addAttribute("chead", "Student Enrollment");// for card-header title h5 tag
model.addAttribute("btnname", "Submit"); // for button text
return "views/studentRegistrationForm";
}
displays the edit or update form
#GetMapping("/editStudent")
public String showStudentRegistrationEditForm(Model model ) {
model.addAttribute("student", new Student());
model.addAttribute("chead", "Edit Student Enrollment");
model.addAttribute("btnname", "Update");
return "views/studentRegistrationForm";
}
}
what you want is th:if tag, you got it almost right but whole wxpression needs to be in brackets th:if="${btnname == 'Submit'}"

Submitting form doesn't work after using Recaptcha v3

I'm trying to use Recaptcha v3 on my form but submitting the form only works when Recaptcha is removed.
When Recaptcha is enabled, I can click on the submit button but nothing happens. I don't even get an error message in the console even though I can see the protected by reCAPTCHA logo in the frontend on the bottom right.
I'm using Laravel 6.
My form template looks like this:
<div class="row mt-150">
<div class="col-12 text-center text-white">
<h1>Contact</h1>
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-4 col-sm-12">
<form action="{{route('contact_form')}}" method="POST">
#csrf
<div class="form-group">
<label for="email" class="text-white">Email address</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="form-group">
<label for="textarea" class="text-white">Message</label>
<textarea class="form-control" id="textarea" rows="3" name="message" required></textarea>
</div>
<input type="submit"
id="submitButton"
class="g-recaptcha btn btn-primary"
data-sitekey="MY-PUBLIC-KEY"
data-callback='onSubmit'
data-action='submit'
name="submit">
</form>
</div>
</div>
<script src="https://www.google.com/recaptcha/api.js"></script>
There is also an app.js included which contains the captcha callback function:
function onSubmit(token) {
document.getElementById("submitButton").submit();
}
window.onSubmit = onSubmit;
Can someone give me a hint what I'm doing wrong implementing recaptcha?
I tried to do it just like this:
Google reCaptcha v3
This will not work because you are trying to trigger submit() on a button. Give the form an id and then trigger submit() on the form
<form action="{{route('contact_form')}}" method="POST" id="contactForm">
#csrf
<div class="form-group">
<label for="email" class="text-white">Email address</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="form-group">
<label for="textarea" class="text-white">Message</label>
<textarea class="form-control" id="textarea" rows="3" name="message" required></textarea>
</div>
<input type="submit"
id="submitButton"
class="g-recaptcha btn btn-primary"
data-sitekey="MY-PUBLIC-KEY"
data-callback='onSubmit'
data-action='submit'
name="submit">
</form>
Then in javascript get the form and trigger submit on it
function onSubmit(token) {
document.getElementById("contactForm").submit();
}
window.onSubmit = onSubmit;

view new div based on option value of select tag using laravel

i have a dropdown list when i select any one option from list i should display an another form with name of the teacher and subject of the teacher in textbox.The form is not displaying.when i select one item it should display the selected name and description box to add subjects of teachers that they interested please help me
view page
<div class="portlet light bordered row">
<h1>Add teacher subject</h1>
<div class="row">
<form action = "{{ url('subjectby/adding/process') }}" method = "POST">
{{ csrf_field() }}
<div class= "col-md-12">
<div class="form-group">
<h3>Choose Teachers </h3>
<div class="input-group">
<div class="ui-widget border-dropdown" style="margin-left:50px;">
<select id="teacher" name="teachers" placeholder="Select Teacher">
<option value="">Select Teacher</option>
#foreach($user as $tec)
<option value="{{$tec->id}}">{{$tec->name}}</option>
#endforeach
</select>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="new">
<div class="form-group">
<div class="col-sm-6">
<label for="inputFacebook">Teacher Name</label>
<input type=hidden value="{{$tec->id}}" name="id">
<input type="text" value="{{$tec->name}}" class="form-control" name="name">
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="inputDescription">Subject Interested</label>
<textarea class="form-control" rows="8" name="intr" placeholder="Enter Subject Interest"> </textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input type="submit" value="add" name=b1>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
This isn't a Laravel specific problem. You are taking about DOM manipulation and so you best bet is to use jQuery or Vuejs or even vanilla Javascript if you so choose. Basically, you will write a script to watch for when your <select> changes, and then based on it's new value, show the part of the form you want.
Keep in mind that Laravel is a backend framework and so the user will never interact with it on a page. After a page loads, Laravel has done all it can do until another request is made. This is why Javascript was born - to let the user change things without reloading the page.

Edit db record with modal window

I'm trying to edit some database record based on an ID that I'm saving into a button value.
#foreach ($employment as $empl)
<button data-toggle="modal" data-target="#edit-empl" href="#edit-empl" class="btn btn-default editbtn-modal" value="{{ $empl->id }}" type="button" name="editbtn">Edit</button>
<h3 class="profile-subtitle">{{ $empl->company }}</h3>
<p class="profile-text subtitle-desc">{{ $empl->parseDate($empl->from) }} - {{ $empl->parseDate($empl->to) }}</p>
#endforeach
As you can see here, I have an edit button with an id attached.
When I click edit I open a modal window to edit the fields and later on submit the form.
The thing is, I'm not sure how to get that id from the button into the modal window so I can compare the values and display the correct fields..
<form class="app-form" action="/profile/employment/edit/{id}" method="POST">
{{ csrf_field() }}
<input class="editID" type="hidden" name="editID" value="">
#foreach ($employment as $empl)
#if ($empl->id == buttonidhere)
<div class="form-group">
<label for="company">Company:</label>
<input type="text" name="company" value="{{ $empl->company }}">
</div>
<div class="form-group">
<label for="month">From:</label>
<input type="date" name="from" value="{{ $empl->from }}">
</div>
<div class="form-group">
<label for="to">To:</label>
<input type="date" name="to" value="{{ $empl->to }}">
</div>
#endif
#endforeach
<div class="row">
<div class="col-sm-6">
<input type="submit" class="btn btn-primary profile-form-btn" value="Save Changes">
</div>
</div>
</form>
I was able to pass the button value into the modal using javascript.. I put it into a hidden input but that doesn't help me at all because I can't get the input value in order to compare the values..
Solution 1: Using ajax
Step 1: Create a route in laravel which will return a JSON object containing employing data of requested employee.
For e.g,
/profile/employment/data/{empl_id}
Will get you employement data of id empl_id.
Step 2: Change your form as below
<form class="app-form" action="/profile/employment/edit/{id}" method="POST">
<input class="editID" type="hidden" name="editID" value="">
<div class="form-group">
<label for="company">Company:</label>
<input type="text" name="company" value="">
</div>
<div class="form-group">
<label for="month">From:</label>
<input type="date" name="from" value="">
</div>
<div class="form-group">
<label for="to">To:</label>
<input type="date" name="to" value="">
</div>
<div class="row">
<div class="col-sm-6">
<input type="submit" class="btn btn-primary profile-form-btn" value="Save Changes">
</div>
</div>
</form>
Step 3: Use javascript(jQuery) to get the data using ajax and load it into the form in modal.
jQuery code:
$(document).on("click", ".editbtn-modal", function() {
var id = $(this).val();
url = "/profile/employment/data/"+id;
$.ajax({
url: url,
method: "get"
}).done(function(response) {
//Setting input values
$("input[name='editID']").val(id);
$("input[name='company']").val(response.company);
$("input[name='to']").val(response.to);
$("input[name='from']").val(response.from);
//Setting submit url
$("modal-form").attr("action","/profile/employment/edit/"+id)
});
});
Solution 2: Using remote modal
Step 1:
Create another blade file for eg. editEmployee.blade.php and add the above form in it.
<form class="app-form" id="modal-form" action="/profile/employment/edit/{{ $empl->id }}" method="POST">
{{ csrf_field() }}
<input class="editID" type="hidden" name="editID" value="{{ $empl->id }}">
<div class="form-group">
<label for="company">Company:</label>
<input type="text" name="company" value="{{ $empl->company }}">
</div>
<div class="form-group">
<label for="month">From:</label>
<input type="date" name="from" value="{{ $empl->from }}">
</div>
<div class="form-group">
<label for="to">To:</label>
<input type="date" name="to" value="{{ $empl->to }}">
</div>
<div class="row">
<div class="col-sm-6">
<input type="submit" class="btn btn-primary profile-form-btn" value="Save Changes">
</div>
</div>
</form>
Step 2: Create a controller which would return the above form as HTML.
Tip: use render() function. example
Step 3: load the form into modal window before showing using javascript(jQuery)
considering your modal id is "emp-modal"
$(document).on("click", ".editbtn-modal", function() {
var id = $(this).val();
url = "/profile/employment/data/"+id;
$('#emp-modal').modal('show').find('.modal-body').load(url);
});
One solution would be to send the details you want the same way you send the id to the modal.
and the proper way to send variables to modal is to include this in the button that opens modal:
data-variablename="{{$your-variable}}"
use this jQuery to get the values of your variables to modal. where edit-empl is the id of your modal and data-target of your button
$('#edit-empl').on('show.bs.modal',function (e) {
var variablename= $(e.relatedTarget).data('variablename');
$(e.currentTarget).find('input[id="yourinputID"]').val(variablename);

Resources