Laravel: Repeating Fields (and Field Groups): Form Model Binding - php

I am building a form in Laravel that deals with an array field in the form of repeatable entities (whether it be single inputs or field groups). I am running into an issue using Form Model Binding when there is either a validation error with a repeated field or a different input in the form.
Right now I'm generating new "instances" of each field by pulling in the view partial with AJAX
# Add Feature
$(document).on 'click', '.js-listing__add-feature', (e) ->
e.preventDefault()
$.ajax
url: dashboard.partials.feature
type: 'GET'
success: (data) ->
$data = $(data)
$('.js-listing__features').append $data
return
return
# Removing features
$(document).on 'click', '.js-listing__remove-feature', (e) ->
e.preventDefault()
$(this).parent('.js-listing__feature-wrapper').remove()
return
So, a user can create new feature inputs on the fly which ultimately combine into an array when saved. The issue becomes when there is a validation issue in the form and we are redirected back. I have not found a way to access the features array in the state it was in (dynamic or not) to spit out what they previously had. In writing this, I guess the issue also becomes clearing out that field if it was the input itself causing the validation issue.
I've searched around in the docs and the 'ole Google for inspiration on this topic, but haven't come across anything. Any nudges in the right direction would be extremely helpful. Thanks as always!
Example of form
#extends('dashboard.master')
#section('content')
<h1>Edit Listing</h1>
#include('dashboard.partials.errors')
{!! Form::model($listing, ['method' => 'PATCH', 'route' => ['dashboard.listings.update', $listing->id], 'class' => 'uk-form']) !!}
<div class="uk-form-row">
{!! Form::label('price', 'Price') !!}
{!! Form::text('price') !!}
</div>
<div class="uk-form-row js-listing__features">
{!! Form::label('features', 'Features') !!}
#if ($listing->features && count($listing->features))
#foreach($listing->features as $key => $feature)
<div class="js-listing__feature-wrapper">
<input type="text" name="features[]" value="{{$feature}}">
<a class="js-listing__add-feature" href="#">+</a>
#if ($key > 0)
<a class="js-listing__remove-feature" href="#">-</a>
#endif
</div>
#endforeach
#else
<div class="js-listing__feature-wrapper">
<input type="text" name="features[]">
<a class="js-listing__add-feature" href="#">+</a>
</div>
#endif
</div>
<div class="uk-form-row">
{!! Form::submit('Update Listing') !!}
</div>
{!! Form::close() !!}
#stop
You'll see my take on what I'd do for the #foreach when I have values to display them when editing the listing. The issue here is not reading the values back (I have set/get attributes working fine for those), but how Form Model Binding works with input arrays so I can still have those values available when they have been dynamically added to the form with AJAX.

I had a similar problem some times ago... My code is surely not very elegant, but it worked ; it may help you to build something...
My trick was to generate a different name for items, distinguish old and new items, count new items:
<input type="text" name="E1-features"> // existing feature #1
<input type="text" name="N1-features"> // new feature #1
<input type="text" name="N3-features"> // new feature #3 (assuming user deleted #2)
<input type="hidden" name="counter" value="3"> // 3 features were added
Server side, the controller distinguishes the existing inputs from the new ones. Here is the code for the new inputs:
Input::flash();
// Existing features
foreach($features as $key => $feature){
if (Input::get('E'.$key.'-features')){
$rules['E'.$key.'-features'] = 'required';
}
}
// New features
for ($i = 1; $i <= Input::get('counter'); $i++) {
if (Input::get('N'.$i.'-features')){
$rules['N'.$i.'-features'] = 'required';
}
}
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()){
return Redirect::to('page')->withErrors($validator)->withInput();
}else{
// data stuff
}

Related

Php laravel 5.3 passing an input value from one blade file to another blade file

I want to pass an input value from one blade file to another blade file.
I'm new to PHP Laravel, and I'm getting an error when attempting to use it.
I think my syntax is wrong here. Can somebody help?
channeling.blade:
<select class="form-control " name="fee" id ="fee"></select>
This is the link to the next page, where i want to send the value of "fee":
<input type="hidden" value="fee" name="fee" />
Click to Channel</p>
This is my web.php:
Route::post('pay', [
'as' => 'fee',
'uses' => 'channelController#displayForm'
]);
This my controller class:
public function displayForm()
{
$input = Input::get();
$fee = $input['fee'];
return view('pay', ['fee' => $fee]);
}
Error message:
Undefined variable: fee
(View: C:\xampp\htdocs\lara_test\resources\views\pay.blade.php)
pay.blade:
<h4>Your Channeling Fee Rs:"{{$fee}}"</h4>
You should use form to send post request, since a href will send get. So, remove the link and use form. If you use Laravel Collective, you can do this:
{!! Form::open(['url' => 'pay']) !!}
{!! Form::hidden('fee', 'fee') !!}
{!! Form::submit() !!}
{!! Form::close() !!}
You can value inside a controller or a view with request()->fee.
Or you can do this:
public function displayForm(Request $request)
{
return view('pay', ['fee' => $request->fee]);
}
I think you can try this, You mistaken url('pay ') with blank:
change your code:
Click to Channel</p>
to
Click to Channel</p>
Further your question require more correction so I think you need to review it first.
You can review about how to build a form with laravel 5.3. Hope this helps you.
You have to use form to post data and then you have to submit the form on click event
<form id="form" action="{{ url('pay') }}" method="POST" style="display: none;">
{{ csrf_field() }}
<input type="hidden" value="fee" name="fee" />
</form>
On the click event of <a>
<a href="{{ url('/pay') }}" onclick="event.preventDefault();
document.getElementById('form').submit();">
Logout
</a>
tl;dr: I believe #AlexeyMezenin's answer is the best help, so far.
Your current issues:
If you have decided to use Click to Channel, you should use Route::get(...). Use Route::post(...) for requests submitted by Forms.
There isn't an Input instance created. Input::get() needs a Form request to exist. Thus, the $fee an Undefined variable error message.
The value of <input type="hidden" value="fee" name="fee"/> is always going to be the string "fee". (Unless there's some magical spell casted by some JavaScript code).
The laravel docs suggest that you type-hint the Request class when accessing HTTP requests, so that the incoming request is automatically injected into your controller method. Now you can $request->fee. Awesome, right?
The way forward:
The BasicTaskList Laravel 5.2 tutorial kick-started my Laravel journey.
I changed the code like this and it worked..
echanneling.blade
<input type="hidden" value="fee" name="fee" />
<button type="submit" class="btn btn-submit">Submit</button>
channelController.php
public function about(Request $request)
{
$input = Input::get();
$fee = $input['fee'];
return view('pay')->with('fee',$fee);
}
Web.php
Route::post('/pay', 'channelController#about' );

Laravel : How to send variable from one page to another in blade

I'm building a laravel application where from The first page I want to send a variable or say value to second page in a form ..How do I do it?
Let's say In my first page I have several buttons so when a user click on any one button, he will be redirected to another page where he has to submit a form.
In first page while he select a button, he automatically select a course_id which will also submit inside the second page form. But How do i send the course_id from the first page button?
<li> A </li>
<li> <a href="{{route('registration')}}" >B</a> </li>
When a user click on the button second page will appear ..Where I'm gonna submit a form where course_id will come from the first page means the <a> tag
Here is my form demo:
{!! Form::open(array('route' => 'postRegistration','class'=>'form-horizontal','method'=>'POST')) !!}
{!! Form::token(); !!}
{!! csrf_field() ; !!}
<div class="form-group">
<label class="sr-only" for="form-first-name">Name</label>
<input type="text" name="name" placeholder="Name..." class="form-first-name form-control" id="form-first-name">
</div>
<div class="form-group">
<label class="sr-only" for="form-email">Email</label>
<input type="text" name="email" placeholder="Email..." class="form-email form-control" id="form-email">
</div>
<div class="form-group">
<label class="sr-only" for="form-last-name">Address</label>
<textarea rows="4" style="height:100px;" name="address" placeholder="Address..." class="form-last-name form-control" id="form-last-name"></textarea>
</div>
<button type="submit" class="btn">Submit</button>
{!! Form::close() !!}
In my database I have to submit the above field as well as the course_id from the database.
How do I do it in Laravel?
Any suggestion or solution please?
You can send the variable as route parameter. To do this change your <a> tags like this.
<li> A </li>
<li> B </li>
Then you need to allow your registration route to take parameter. Suppose your route is like this
Route::get('/registration', [
'as' => 'registration', 'uses' => 'SomeController#method'
]);
Change it to
Route::get('/registration/{course_id}', [
'as' => 'registration', 'uses' => 'SomeController#method'
]);
Now you have to add this parameter into your SomeController#method
public method($course_id){ ... }
Now pass this $course_id to your form view. To submit this variable with your other fields you can add this as hidden input field.
<div class="form-group">
<input type="hidden" name="course_id" value="{{ $course_id }}">
</div>
So you want to create page with multiple course links and each link redirects to registration page with the course id to be used in the registration form.
Your a href link should look like this
{!! link_to_route('registration',
$title = 'Course 1', $parameters = ['1'], $attributes =
['class'=>'btn btn-success']) !!}
Routes file web.php
Route::get('/registration/{course_id}','
CourseRegistration#showForm')->name('registration');
CourseController CourseController
public function showForm($course_id){
return view('registration')->with('courseid',$course_id);
}
Now you can access the course id with $courseid in view. If you want to pass it in form create a hidden or input tag with the data.
According to me, you're looking for a type of web app in which when a user submits a form the page opens up with the registered user details.
This can be done in Laravel like this:
routes.php
// For submitting form on this route
Route::post('users/register', 'UsersController#create')->name('users.register');
// For showing user's profile via user's id
Route::get('users/{id}/profile', 'UsersController#show')->name('users.profile');
UsersController.php
class UsersController {
public function create() {
$inputs = request()->all();
// Use Eloquent to save user info to DB and fetch insert id from DB...
return redirect()->route('users.profile', array('id' => $insert_id));
// Will open registered user profile page
}
public function show($id) {
$user = User::find($id);
if(!$user) {
abort('404');
}
return view('users/profile', compact('user'));
// At the users/profile.php page you can use $user variable to populate user's info
}
}
Usage of route method with passing data with route in Blade
{{ route('users.profile', array('id' => $user->id)) }}
For more help, see this >>
Hope this helps you!

How do I give a variable to my blade and save them to a variable?

My problem is a little bit complicated to explain. I'm doing a blog and did something like a topic section. I have a topic table and a thread table. In my thread table is a 'topic' attribute. No I want that if I'm doing a new thread, I also want to save the topic, the user currently is in right now.
My send button with the variable is this:
<a href="{{ action('Test\\TestController#add', [$thread->thema]) }}">
<div class="btn btn-primary">Thread hinzufügen</div>
</a>
My add-route:
Route::get('/add/{thread}', 'Test\\TestController#add');
My controller function just send's me to the thread creating form.
My creating thread - form :
{!! Former::horizontal_open()->action(action('Test\\TestController#store')) !!}
{!! Former::text('thread')->label('Title:')->autofocus() !!}
{!! Former::textarea('content')->label('Content')->rows(10) !!}
{!! Former::large_primary_submit('Add Thread') !!}
{!! Former::close() !!}
Well, after I pressed the submit button, the thread get saved, but without the topic! :/
According to the following route:
Route::get('/add/{thread}', 'Test\\TestController#add');
You'll get the $thread->thema inside your TestController#add method so your method should be able to recieve that param/variable, for example:
public function add($thread)
{
// Now you may pass the $thread to form and keep the value in a hidden
// text box, to pass to the for the form, add the $thread using with:
return view('FormView')->with('thread', $thread);
}
In the form, create a hidden input:
<input type="hidden" name="thread" value="{{ old('thread', $thread) }}" />
Or maybe this (if it works, not sure about the former tho):
{!! Former::hidden('thread', old('thread', $thread))->label('Title:')->autofocus() !!}

Form element created by JQuery not recognized by Controller in Laravel

Good afternoon,
I have been trying to get this to work for a while now but can't seem to. I have a view with a form. In that form is a select dropdown and bunch of inputs that pass info to the Controller for processing.
The problem is, the form needs to be able to change itself by adding or removing new inputs depending on which option is selected in the select.
What I did was use JQuery to append and remove elements. It works fine front end, but elements created this way are not recognized by the controller. Please take a look:
Controller
public function userface2show() {
$keymaker = Request::get('Search');
dd(Request::all());
//this works only on the original elements in the view, any element created by my JQuery does not reflect in the dd(Request::all());
}
View:
<script>
$(document).ready(function(){
$(function(){
$('#specialselect').change(function() {
if($("#specialselect option:selected" ).text() == "Year") { // activates the change when option from the select is activated
$("#selectornode").remove(); // removes original element
$("#selectorbox").append("<input id='selectornode1' name='Search1' type='text'>"); // adds new element with another "name"
}
else {
$("#selectornode1").remove(); // removes new element
$("#selectorbox").append("<input id='selectornode' name='Search' type='text'>"); // creates replicate of the original element. This replica does not work either.
}
});
});
});
</script>
<table class="formstyle">
{!! Form::open(array('action' => 'MasterController#userface2show')) !!}
<tr>
<td>
{!! Form::label("Select Area/Field of Study") !!}
</td>
<td>
{!! Form::select('Area', $Area) !!}
</td>
<td>
{!! Form::label("Specify Search Parameter") !!}
</td>
<td>
{!! Form::select('Parameters', $Parameters, 'default', array('id' => 'specialselect')) !!}
</td>
<td>
{!! Form::label("Input Word to Search", null, array('id' => 'selectortext')) !!}
</td>
<td id="selectorbox">
{!! Form::text('Search', null, array('id' => 'selectornode')) !!} // this is the only element that needs to be changed.
</td>
<td>
{!! Form::submit('Go', ['class' => 'buttonite']) !!}
</td>
</tr>
{!! Form::close() !!}
</table>
Is there any way to make these newly created form inputs work?
Thanks guys, any help would be appreciated.
You have not actuly connected the request to your controllers function.
Like discribed here.
Change your controllers function to this and you should be able to access the variable now.
public function userface2show(Request $request) {
$keymaker = $request->input('Search');
dd($request);
}
Good afternoon peeps,
You are never going to believe what fixed this problem. Me and a bunch of other devs took a look at the problem and couldn't tell what was wrong, so we started removing elements one by one to see what was causing the problem.
When we removed the HTML <table> format, It started working. The <tr>s and <td>s were interfering with the front-end's ability to relay the information to the back end.
Thank you all for checking out the problem.

Posting a Laravel form is not working

I am setting up a simple form in laravel:
This is the route file:
Route::get('backoffice/upload', [ 'as' => 'backoffice/upload',
'uses' => 'UploadController#uploadForm']);
Route::post('backoffice/saveimage',[ 'as' => 'backoffice/saveimage',
'uses' => 'UploadController#saveImage']);
This is the controller:
class UploadController extends \BaseController
{
public function uploadForm()
{
return View::make("backoffice.upload.create");
}
public function saveImage()
{
return "Uploading...";
}
}
And this is the View file:
<h1>Upload Image</h1>
{{ Form::open(['action' => 'UploadController#saveImage']) }}
<div class='formfield'>
{{ Form::label('newfilename','New File Name (optional):') }}
{{ Form::input('text','newfilename') }}
{{ $errors->first('newfilename') }}
</div>
<div class='formfield'>
{{ Form::submit($action,['class'=>'button']) }}
{{ Form::btnLink('Cancel',URL::previous(),['class'=>'button']) }}
</div>
{{ Form::close() }}
// Generated HTML
<h1>Upload Image</h1>
<form method="POST" action="http://my.local/backoffice/saveimage" accept-charset="UTF-8"><input name="_token" type="hidden" value="x9g4SW2R7t9kia2B8HRJTm1jbLRl3BB8sPMwvgAM">
<div class='formfield'>
<label for="newfilename">New File Name (optional):</label>
<input name="newfilename" type="text" id="newfilename">
</div>
<div class='formfield'>
<input class="button" type="submit" value="Create">
</div>
</form>
So, if I go to: http://my.local/backoffice/upload I get the form with the HTML above.
However, if I type anything, then click SUBMIT, I return to the form but now have the following URL:
http://my.local/backoffice/upload?pz_session=x9g4SW2R7t9kia2B8HRJTm1jbLRl3BB8sPMwvgAM&_token=x9g4SW2R7t9kia2B8HRJTm1jbLRl3BB8sPMwvgAM&newfilename=ddd
This makes no sense to me. Up until now I have always used route::resource when dealing with forms, and had no problem. I am trying to do a simple form with GET and POST and am having no end of grief. What am I missing?
Furthermore, if I modify routes.php and change it from post to any, then open a browser window and type: http://my.local/backoffice/saveimage then I get the message "Uploading..." so that part is working ok.
Found the solution. In making the backoffice of the system, I had re-used the frontoffice template but removed all the excess. Or so I had thought. However, the front office header template had a form which I had only partially deleted.
So the problem was that there was an opening FORM tag I didn't know about. Consequently, when I clicked on submit to my form, it was actually submitting to this other form.
As the other form had no action it was default to itself.
Of course, had I just validated the HTML this would have shown up straight away. The lesson learned here is to validate my html before submitting questions!
Try this, and be sure to correctly configure your url at app/config/app.php
{{Form::open(['url'=>'backoffice/saveimage'])}}
//code
{{Form::close()}}

Categories