So basically I have a favorited value for my tasks. It's named 'favorited' and has a boolean so 1/true or 0/false. (mySQL)
Currently, each row (a task) has a font awesome star, if favorited is 1, it will become fas with text gold so it'll show a gold star. If favorited is 0, it will become far, which makes it a white star with the inside empty.
<i class="{{ $task->favorited ? 'text-gold fas' : 'far' }} fa-star"></i>
It has class del_link which triggers a javaScript/jQuery function. Which submits the <a> parent form
$('.del_link').each(function(){
$(this).on('click', function(event){
$(this).parent().submit();
});
});
Now this is the form wrapped around the <a></a>
<form method="post" action="{{ route('tasks.update', $task) }}">
#csrf #method('patch')
<input type="hidden" name="favorited" value="{{ $task->favorited ? 0 : 1 }}">
<i class="{{ $task->favorited ? 'text-gold fas' : 'far' }} fa-star"></i>
</form>
So basically, if favorited === 1, then set the favorited value to 0, so when I submit the form, I set the favorited value to 0. Now this for some reason doesn't work. Whenever I press the star so I can favorite it, it works, but when I do it the other way around to unfavorite; it doesn't.
This is my code for the TaskController.php
public function update(Request $request, Task $task)
{
$task->update([
'favorited' => request()->has('favorited')
]);
return back();
}
Actually, the code above and the method is something I got from the Laravel 5.8 scratch video. (Laracasts laravel tutorial)
It has worked for me using a checkbox instead of using a star, but it doesnt work this way.
I've tried using a lengthy if statement, that if request was 1 I would set it to 1. (request = 1 means that the hidden input was 1 so it wasn't favorited) and an else, so if 0, it would set it to 0 thereby unfavoriting it.
But in that case, it still didnt work. I've dd the request, task and text to show me where I am and what I get, but to no avail.
Thanks for any help
When you use request()->has('favorited'), it return true when the request contain the input favorited=1 or favorited=0 (both cases).
It does work with a checkbox because when an input type="checkbox" is unchecked, it is not send in the request.
When it's an input type="hidden", favorited will be present in the request all the time.
You should change it to 'favorited' => (int)(bool)request()->input('favorited')
According to the Laravel documentation $request->has('favorited') checks if favorited is present in the request. Whether it's set to 0, 1, or any other value does not impact the returned value.
Instead, using (bool)$request->input('favorited') should work. Or if you haven't cast the favorited attribute to a boolean (bool)$request->input('favorited') ? 1 : 0.
If this doesn't work, the value isn't set properly in the request, so it's most likely a front-end issue. In that case, dd($request->input('favorited')) to see if the value is present as expected. I don't immediately see an issue with your view and js.
and welcome to Stack Overflow.
Your problem is on both, frontend and backend:
Backend: request()->has('field');
The request will always have this field which means the value of it is 1 all the time since you have input field presented.
Frontend: You are not changing the value of the input.
Two fixes for this:
1. Frontend you can set Javascript to change the input value when you press this to the opposite.
Do the same as #1 on the backend, which is easier.
So, this should work for you:
// First validate you have that field.
request()->validate([
'favorited' => ['required'],
]);
// Then set the favorited to opposite of current.
$task->update([
'favorited' => !$task->favorited // notice the "!" (take oposite value)
]);
Edit:
By the way you can get rid of Javascript by removing input hidden and making submit the value you want to use, since its either 0 or 1.
So: remove the input type="hidden", and change from a-href to button.
<button name="favorited">
<i class="{{ $task->favorited ? 'text-gold fas' : 'far' }} fa-star"></i>
</button>
That should do the thing.
Related
I'm trying to add functionality to my edit form. Perhaps not a best practice but...
I want to keep the original url for several updates. When a user first lands on edit form (from list or single view) I want a Cancel button that redirects user back to.. "referrer". After an update I redirect back to edit form with success message. I want to hide the Cancel button and show Back button. User can edit multiple times.
I tried to pass the original url through Request, but that didn't end well. Now I'm trying with storing the url in session. Ifs work, but the session item value gets overwritten in second iteration.
Perhaps I'm using the session the wrong way? Any idea? Perhaps another "better" way?
The code in my edit.blade
#if(url()->current() != URL::previous())
#if(Session::has('myreferrer'))
{{ Session::forget('myreferrer') }}
#endif
{{ Session::put('myreferrer', URL::previous()) }}
Cancel
#else
Back
#endif
Session::pull() fetches the value from the session and removes it. This is why the page doesn't work the second time:
User visits edit from previous
URL::current() != URL::previous()
'myreferrer' set to previous
Show Cancel button
User fills and saves edit form
URL::current() === URL::previous()
'myreferrer' set to null (because Session::pull())
Show Back button
User saves edit form again
URL::current() still === URL::previous()
'myreferrer' is still null
Show Back button again with an empty URL (because 'myreferrer' is null) which the browser interprets as the current URL
We can use Session::get() to fetch the value and leave it in the session, but this pollutes the session because 'myreferrer' still exists when the user navigates away from the edit form.
More importantly, this logic doesn't belong in a view template. Instead we'll use the controller to pass the value of 'myreferrer' using a hidden input field:
public function edit($id)
{
// fetch data...
return view('edit')
// if "myreferrer" isn't in the session yet, use previous URL:
->with('myreferrer', Session::get('myreferrer', URL::previous()));
}
public function update(Request $request)
{
// save data...
return back()
->with('success', 'Your success message.')
// "flashes" to the session only for the next page load:
->with('myreferrer', $request->get('myreferrer'));
}
<form ...>
<input type="hidden" name="myreferrer" value="{{ $myreferrer }}"/>
...
#if (Session::has('success'))
Back
#else
Cancel
#endif
I'm assuming you actually need the previous URL to be dynamic, such as if the user can open the edit form from different pages. Named routes offer better semantics when you don't need this flexibility.
For the sake of learning, here are some other pointers related to your code:
We don't need Session::has() before Session::forget() (forget() skips if the key doesn't exist). Additionally, the call to Session::put() afterward overwrites the value here anyway, so we can remove the whole #if(Session::has('myreferrer')) block.
url()-> and URL:: do the same thing. We should probably choose one for consistency.
I'm using Laravel Collective for Forms and having an issue with checkbox.
Here is what I'm doing :
{!! Form::checkbox('independent',null,['class'=>'form-control', 'required' => 'required'])!!}
I've tried changing values for "null", added one more parameters as suggested by many while googling for solution but nothing seems to be working.
If anyone know the solution or having same issue, please share.
The documentation states that the third parameter is a boolean that determines if the checkbox is checked, you have an array as the third parameter. Php interprets an array as true, this is why your checkbox is always checked.
You should add true or false as the third parameter and add the options array as a fourth parameter. This can be found in the source code on GitHub.
{!! Form::checkbox('independent', null, false) !!}
I have one really simple question. I have a form with three groups of dynamically generated check boxes. Let's say one of these groups of check boxes needs to have all check boxes as default set.
This is not a problem, the problem comes when I submit the form and I need to have the state of the checkbox.
Here is the HTML code I generate:
#for($i=0;$i<24;++$i)
{!! Form::checkbox('check_hour[]', $i, $check_hour[$i], ['class' => 'check_hour']) !!} {{($i+1)}}h
#endfor
and here is the code in the Controller:
for($i=0;$i<24;++$i) $check_hour[$i] = (isset(Input::get('check_hour')[$i])) ? true : false;
In this situation I have no problem to save the checkbox state, but I need all check boxes to bet set as default.
This is my html blade code
{{Form::checkbox('remember_me', '', array('id'=>'remember_id'))}}
<label for="remember_id">Remember me</label>
This is my controller code:
echo Input::get('remember_me');exit;
The result is always empty, why please?
The checkbox is always checked when I run the page, why please?
Thanks
Please have a look on the [parameter list of the Form::checkbox() method][1].
The second parameter is your checkbox value. You manually set it to an empty string. Set it to null in order to keep the browsers default values (laravel default is 1). The third parameter is a boolean. Set it to true to check the box and false to uncheck it.
The fourth parameter is your options array where you can specify your id. So the correct method call should be:
{{Form::checkbox('remember_me', null, false, array('id'=>'remember_id'))}}
Update:
Checkboxes that are not checked, will not be included in your POST data. So the only reliable way to verify that a checkbox has been checked is to check if it is set. That can be done using isset() with regular PHP functions, or if laravel is being used, by using Input::has() which returns a boolean dependent on whether your input data contains a given key.
You did not add a value to the checkbox
{{Form::checkbox('remember_me', 'value goes here', true, array('id'=>'remember_id'))}}
The second param is the value
Normally I write the checkbox without blade and I can do with it whatever I want, like normal HTML. I don't see why you can do it the normal HTML way, because it always ends up doing the same thing you expert.
{!! Form::label('Test-2') !!} {!! Form::checkbox('ch[]', 'value-2', false); !!}
I have a form where I show some items, which can be selected by the user.
There are over 1000 items so I'm using pagination.
What would be the best way to persist the checked items, when user go to the next page?
To store all these items in hidden fields wouldn't be an option, because they are to much items.
My View:
#foreach($articles['uncommitted'] as $article)
<tr>
<td><input type="checkbox" name="articles[]"></td>
<td>{{{$article->articlename}}}</td>
<td>{{{$article->category->catname}}}</td>
<td>{{{strftime('%d.%m.%Y %H:%M', strtotime($article->created_at))}}
<td>{{{$article->rrp}}}</td>>created_at))}}}</td>
</tr>
#endforeach
{{$links}}
This form will be paginated.
As far as I understand you are facing two problems: persisting the checked items across pagination request, and retrieving the checked items back to the view.
To persist the checked items across pagination request, I would flash the checked items into the Session. The controller method will look something as follows.
public function fill_form()
{
$items = Item::paginate(25);
// Retrieve checked items in session.
$checked_items = []
if (Session::has('checked_items'))
$checked_items = Session::get('checked_items');
// Persist new checked items.
$checked_items = array_merge($checked_items, Input::get('item'));
Session::flash('checked_items', $checked_items);
return View::make('form')
->with('items', $items);
}
As you can see the checked items will be available in the session within pagination requests.
Now for the case to display the checked items back to the view I would send the checked items in session to the view via old input. That said, the return value would be changed as follows.
public function fill_form()
{
# code intentionally omitted #
return View::make('form')
->with('items', $items)
->withInput($checked_items);
}
Then in your views the checked items will persist their checked value. Obviously, you should use Laravel to generate your checkboxes.
How to get all item (checked or not) on submit?
Maybe, if you are render items with checkboxes you will need to know which of those checkboxes were checked and which not when paginating. A simply solution will be adding an extra input hidden field for each checkbox with a default value, it will look as follows:
{{ Form::hidden('item1', 'off') }}
{{ Form::checkbox('item1', 'on') }}
{{ Form::hidden('item2', 'off') }}
{{ Form::checkbox('item2', 'on') }}
{{ Form::hidden('item3', 'off') }}
{{ Form::checkbox('item3', 'on') }}
After submitting the form, when paginating, for checked item you will receive the expected value, for those not checked you will receive the hidden value.
Note 1, it is important to put the hidden input before each checkbox.
Note 2, each hidden input should have the same name as the checkbox.
Unless I misunderstood your question, I think what you're looking for is caching: http://four.laravel.com/docs/cache
Here's an excerpt from the docs:
Database Cache
When using the database cache driver, you will need to setup a table to contain the cache items. Below is an example Schema declaration for the table:
Schema::create('cache', function($table)
{
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
If you're wanting to store form data across requests, then you'll want to use Session - excerpt from the docs (http://four.laravel.com/docs/session):
Database Sessions
When using the database session driver, you will need to setup a table to contain the session items. Below is an example Schema declaration for the table:
Schema::create('sessions', function($table)
{
$table->string('id')->unique();
$table->text('payload');
$table->integer('last_activity');
});