Laravel collective custom forms, action Controller#update not defined - forms

This is my route:
Route::get('admin/edit-news/{id}', 'AdminNewsController#edit');
My Controller#update method:
public function update(Request $request, $id)
{
$news = News::find($id);
$news->title = $request->input('title');
$news->content = $request->input('content');
$news->save();
return redirect ('/admin');
}
and my view with custom form:
{{ Form::open(['action' => ['AdminNewsController#update', $news->id], 'method' => 'POST']) }}
{{ Form::bsText('title', $news->title) }}
{{ Form::bsTextArea('content', $news->content) }}
{{ Form::hidden('_method', 'PUT') }}
{{ Form::bsSubmit('Confirm', ['class' => 'btn btn-primary center-block']) }}
{!! Form::close() !!}
The error im getting is
"Action App\Http\Controllers\AdminNewsController#update not defined. (View: D:\xampp\htdocs\laravelhotel\resources\views\admin\news\edit_news.blade.php)"
I dont know why, since the action i put is update function, and i have all the components registered in FormServiceProvider.

If you use PUT method, which is simulated by POST form-method and _method field ({{ Form::hidden('_method', 'PUT') }}), you need to use the corresponding route:
Route::put('admin/edit-news/submit', 'AdminNewsController#update');
// ^^^

Related

Laravel Blade Form::checkbox rendered as select

I have a form that should display as checkboxes but is appearing as a select dropdown.
In the controller I defined the variables:
$user = Auth()->user();
$users = User::all();
$assignedUsers = User::where('assigned', true)->get();
Here is where the form is defined in the view:
{{ Form::open( route('users.access', [$user->id]), ['type' => 'PUT']) }}
{{ Form::checkbox(
'Users',
[
'label' => __('Select Users'),
'options' => $users,
'value' => $assignedUsers
]
) }}
{{ Form::button('submit', ['label' => __('Save changes')]) }}
{{ Form::close() }}
The form is rendering but not as checkboxes but a select dropdown. What am I missing here?
Form::checkbox() method accepts 3 arguments, name, value, and default. You seem passing wrong arguments for the checkbox list so it renders as dropdown, to make a checkbox list, you and use a loop, should be something like so:
#foreach ($users as $user)
<label>
{{ Form::checkbox('users[]', $user->id, isset($assignedUsers[$user->id])) }}
{{ $user->name }}
</label>
#endforeach
Note that I have converted your $assignedUsers variable to key by id for more convernience. You can use your own check method.
$assignedUsers = User::where('assigned', true)->get()->keyBy('id');

Symfony - Add text in generated form

I'd like to do something quite simple, but I can't figure out how to manage it. I have a form:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
There are several text field in it. I'd like to "insert" some text (like <p>my Text</p>) between two text fields (let's say between name text field and description text field). Form are generated with form builder tool. I've tried something like:
$builder
->add('stuffName') // works well (text field 1)
->add('addedText', 'text', array('label' => 'my Text')) // Trouble here!
->add('stuffDescription'); // works well (text field 2)
But it generates a text field (and not a simple text). I don't care if the text is set in the form builder or directly in twig template... As long as it is between my two text fields. Any idea?
Thanks a lot!
Symfony forms contain only form fields. Any additional content you want has to be added by the template.
This means you'll have to output the form field-by-field. Your form, for example might look like this:
{{ form_start(form) }}
{{ form_row(form.stuffName) }}
<p>Your Text</p>
{{ form_row(form.stuffDescription) }}
{{ form_end(form) }}
For more more information on how you can customize form rendering, please see the forms chapter in the Symfony documentation.
The keyword in this question is generated.
Let's assume, that you build a form generator in Symfony. You have entities like Form, Fields and Fields Items (it's options for select box or buttons for radio button field).
So you have this entities and you create a service to create a form from the data. In the service you build the form ($this->buildedForm - generated form, $page->getFormData() - put the data to the constructed form):
$this->buildedForm = $this->formFactory->create(
'form',
$page->getFormData(),
['action' => '/page/formview/' . $task->getId()]
);
foreach($fields as $field) {
$fieldBuilderMethod = 'construct' . ucfirst($field->getType()) . 'Field';
if (method_exists($this, $fieldBuilderMethod)) {
$this->$fieldBuilderMethod($field);
}
}
return $this->buildedForm;
And you have methods for each type like (examples for Symfony 2):
private function constructInputField(FormField $field)
{
$this->buildedForm->add(
$field->getFieldName(),
'text',
[
'label' => $field->getName(),
]
);
}
private function constructTextareaField(FormField $field)
{
$this->buildedForm->add(
$field->getFieldName(),
'textarea',
[
'label' => $field->getName(),
]
);
}
You can now create your custom form type to paste a text in the generated form (it could be placed in the form folder of your bundle and retrieved with namespace "use"):
private function constructSimpletextField(FormField $field)
{
$this->buildedForm->add(
$field->getFieldName(),
new SimpletextType(),
[
'label' => $field->getName(),
'data' => $field->getPlaceholder(),
]
);
}
What in this custom field?
namespace Myproject\MyBundle\Form\TaskTypes;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SimpletextType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'disabled' => true,
'required' => false,
'mapped' => false,
]);
}
public function getParent()
{
return 'text';
}
public function getName()
{
return 'simpletext';
}
}
And the whole magic comes out in the template. For your custom form type you need to make a custom theme (see https://symfony.com/doc/2.7/form/form_customization.html#form-customization-form-themes). And there:
{% block simpletext_label %}{% endblock %}
{% block simpletext_widget %}
<p>{{ form.vars.data }}</p>
{% endblock %}
{% block simpletext_errors %}{% endblock %}
See, no label, no errors (it just a text) and only text in the field widget. Very handy for generated forms with dynamic template.
EDIT - Symfony 5
In Symfony 5, this solution became simplier. The form customization doesn't changes, and the php code became like this:
namespace Myproject\MyBundle\Form\TaskTypes;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SimpletextType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'disabled' => true,
'required' => false,
'mapped' => false,
]);
}
public function getBlockPrefix(): string
{
return 'simpletext';
}
}
It's used like this :
public function buildForm(FormBuilderInterface $builder, array $options): void {
/* … */
$builder->add('anykey', SimpleTextType::class, [
'data' => "Type your text here",
]);
/* … */
}
Here a sample code which would be self explain
{{ form_start(form, { 'attr': { 'class': 'form-horizontal form-bordered'} }) }}
<div class="form-group">
<div class="col-md-3 ">
{{ form_label(form.User, 'Label text', { 'attr': {'class': 'control-label'} }) }}
</div>
<p>You are free to add whatever you want here</p>
<div class="col-md-9">
{{ form_widget(form.User, { 'attr': {'class': 'form-control'} }) }}
</div>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
In any case, the symfony documentation is pretty clear and well-explain about this point.

Laravel 4 change form open with if else statement

I'm new to Laravel and trying some stuff out. Hope you guys can point me in the right direction.
I have a form to add categories on a the page with the overview of all the categories. Now I'm routing to the same page when you want to add or edit a category. Problem is, I want the normal add form to show when the url is category/add and when the url is category/edit/id I want it to show the form to edit (with form model binding). I placed the code in an if else statement, but it always shows the edit form, therefore if I want to add a new category on the url categories I get an error because it's the edit form.
Here's the code in the index.bade.php:
#if(Request::url() === 'categories' )
{{ Form::open(array('url' => 'category/add', 'class' => 'form-horizontal')) }}
#else
{{ Form::model($category, array(
'url' => 'category/edit/'.$category->id ,
$category->id,
'class' => 'form-horizontal'))
}}
#endif
My controller:
public function index()
{
$categories = Category::get();
$category = new Category();
View::share('title', 'Mini Blog - Categories');
$view = View::make('category.index')->with('category', $category);
$view->categories = $categories;
return $view;
}
public function edit($id)
{
$categories = Category::get();
$category = Category::find($id);
View::share('title', 'Mini Blog - Edit category');
return View::make('category.index')->with(array('category' => $category, 'categories' => $categories));
}
Is this the way to go? Or is there a better way?
Instead of checking the URL I suggest you depend on the model variable. Ever Eloquent model has a property exists that tells you if the model has been loaded from the DB or it's a new instance.
#if( ! $category->exists)
{{ Form::open(array('url' => 'category/add', 'class' => 'form-horizontal')) }}
#else
{{ Form::model($category, array(
'url' => 'category/edit/'.$category->id ,
$category->id,
'class' => 'form-horizontal'))
}}
#endif
Actually you can use Form::model with an empty model as well, so you should be able to reduce it to this:
{{ Form::model($category, array(
'url' => ($category->exists ? 'category/edit/'.$category->id : 'category/add'),
'class' => 'form-horizontal'))
}}
There is a much better way.
In your controller do this:
public function create()
{
return View::make('create');
}
public function edit($id)
{
return View::make('edit')->withId($id);
}
Then in your views you have
Create.blade.php
{{ Form::open(array('url' => 'category/add', 'class' => 'form-horizontal')) }}
#include ('form')
{{ Form::close() }}
Edit.blade.php
{{ Form::model($category, array('url' => 'category/edit/'.$category->id, category->id, 'class' => 'form-horizontal')) }}
#include ('form')
{{ Form::close() }}
Form.blade.php
//Put your HTML form stuff here

Keep form values when redirect back in Laravel 4

I'm trying to keep the values of a form when Redirect::back on Laravel 4, but I can't find a way to do this.
This is my form:
{{ Form::open(array('route' => 'generate', 'files' => true)) }}
{{ Form::radio('myType', '1', true); }}
{{ Form::label('myType', '1'); }}
{{ Form::radio('myType', '2'); }}
{{ Form::label('myType', '2'); }}
{{ Form::radio('myType', '3'); }}
{{ Form::label('myType', '3'); }}
{{ Form::text('myName'); }}
{{ Form::file('uploadImage'); }}
{{ Form::submit('Go'); }}
{{ Form::close() }}
And my controller:
$validator = Validator::make(Input::all(), array('uploadImage' => 'required|image', 'myName' => 'required'));
if ($validator->fails()){
return Redirect::back()->withErrors($validator);
}
I tryed something like:
return Redirect::back()->withErrors($validator)->with('nameValue', Input::get('myName'));
And then in the view:
{{ Form::text('myName', $nameValue); }}
But it still doesn't work. Any help will be appreciated.
if ($validator->fails()){
return Redirect::back()->withErrors($validator);
}
change to,
if ($validator->fails()){
return Redirect::back()->withErrors($validator)->withInput();
}
you can retreive the value by Input::old() method.
read more
you tried: return Redirect::back()->withErrors($validator)->with('nameValue', Input::get('myName'));
above, you can get the value from Session.
Session::get('nameValue')
Hey If you are using laravel 5.2 or greater version than you dont need to write
Redirect::back()
You can simply use back() helper function to do this.
so you can replace your code with below code.
if ($validator->fails()){
return Redirect::back()->withErrors($validator)->withInput();
}
Here is a link for back() helper function documentation.

bootstrap style conflicts with forms bound with models laravel 4

I am developing an application with laravel 4, I have forms that are filled with data from a model, in other words a model is bound to the form
I need to add some bootstrap style to the form and I do it this way
this is my view file:
{{
Form::model($user, array( $user->id))
}}
{{ Form::label('last_name', 'Last Name') }}
{{ Form::text('last_name', '', array('class' => 'form-control')) }}
{{ Form::close() }}
and this is my controller code:
public function edit(){
$user = User::find(Auth::user()->id);
return View::make('edit')->with('user',$user);
}
The Issue:
As soon as I add this class to the form's element the content of the form will disappear and no data is bound to it anymore, how should I fix it?
I found the answer the second argument of this
{{ Form::text('last_name', '', array('class' => 'form-control')) }}
is the input value of text field so it should be like this:
{{ Form::text('last_name', $user->last_name, array('class' => 'form-control')) }}