I have a simple task list project under Laravel.
When I click a checkbox it does not show a checked condition. (The second item is in the true condition in the database and thus shows checked. I cannot uncheck this item) I have searched for an answer to why on the net but cannot find a solution or reason.
Code:
home.blade.php (in views folder) -
#extends('layouts.main')
#section('content')
<h1>Tasks</h1>
<ul>
#foreach ($items as $item)
<li>
{{ Form::open() }}
<input type="checkbox" onClick="this.form.submit()" {{ $item->done ? 'checked' : '' }}>
<input type="hidden" name="id" value="{{ $item->id }}">
{{ $item->name }}
{{ Form::close() }}
</li>
#endforeach
</ul>
#stop
HomeController.php (inControllers folder) -
<?php
class HomeController extends BaseController {
public function getIndex() {
$items = Auth::user()->items;
return View::make('home', array(
'items' => $items
));
}
public function postIndex() {
$id = Input::get('id');
$user_id = Auth::user()->id;
$item = Item::findOrFail($id);
if($item->owner_id == $userId) {
$item->mark();
}
return Redirect::route('home');
}
}
Item.php (in models folder) -
<?php
class Item extends Eloquent {
public function mark() {
$this->$done = $this->done ? false : true;
$this->save();
}
}
routes.php -
<?php
Route::get('/', array('as' => 'home', 'uses' => 'HomeController#getIndex'))->before('auth');
Route::post('/', array('uses' => 'HomeController#postIndex'))->before('csrf');
Route::get('/login', array('as' => 'login', 'uses' => 'AuthController#getLogin'))->before('guest');
Route::post('login', array('uses' => 'AuthController#postLogin'))->before('csrf');
in your code, you never update the model's done value. i assume, you want to change it with the post method. so you'd need to take the value from the checkbox name (e.g. Input::get('box-ID'))
you could also create a checkbox using the form class:
// public function checkbox($name, $value = 1, $checked = null, $options = array())
{{ Form::checkbox('name', 'value', true, ['onClick' => 'alert(123)']) }}
reference: Formbuilder -> checkbox
You should modify your form like this. It works me I hope will work for you also.
{{ Form::open(['route' => ['items.update', $items->id], 'class' => 'form-inline', 'method' => 'put']) }}
Thanks
Related
I'm trying to bind a default value to a select tag. (in a "edit view").
I know this should be easy, but I think I'm missing something.
I have:
User.php (my user model)
...
public function groups()
{
return $this->belongsToMany('App\Group');
}
public function getGroupListAttribute()
{
return $this->groups->lists('id');
}
...
UserController.php (my controller)
...
public function edit(User $user)
{
$groups = Group::lists('name', 'id');
return view('users.admin.edit', compact('user', 'groups'));
}
...
edit.blade.php (the view)
...
{!! Form::model($user, ['method' => 'PATCH', 'action' => ['UserController#update', $user->id]]) !!}
...
...
// the form should be binded by the attribute 'group_list' created
// at the second block of 'User.php'
// performing a $user->group_list gets me the correct values
{!! Form::select('group_list[]', $groups, null, [
'class' => 'form-control',
'id' => 'grouplist',
'multiple' => true
]) !!}
...
I did a dummy test in my blade, and have gotten the correct results:
#foreach ($user->group_list as $item)
{{ $item }}
#endforeach
This lists the values that should be selected by default..
I also tried to put $user->group_list as third parameter from the Form::select, but this didnt work ether...
I have no clue what i'm doing wrong.. any hints on this one?
edit
when I do:
public function getGroupListAttribute()
{
//return $this->groups->lists('id');
return [1,5];
}
The item are correctly selected,
now i know i have to grab an array from the collection..
digging deeper.. :)
found it
User.php:
...
public function getGroupListAttribute()
{
return $this->groups->lists('id')->toArray();
}
...
could it be easier?
Nice regards,
Kristof
You shouldn't put null in the selected defaults (3rd) argument.
{!! Form::model($user, ['route' => ['user.update', $user->id]]) !!}
{!! Form::select(
'group_list[]',
$groups,
$user->group_list,
['multiple' => true]
)
!!}
in my application i want to simplify forms and change Form::model to use both of Update and Insert, for have this ability i'm create this route:controller to show View and modrate it:
Route::controller(
'customers' , 'customersController',
array(
'getIndex' =>'customers.index',
'postUpdate'=>'customers.update'
)
);
customersController controller class:
<?php
class customersController extends \BaseController
{
public function getIndex()
{
if ( Auth::check() ){
$customers = new Customers;
return View::make('layouts.customers')->with('customers', $customers);
}
return Redirect::route('dashboard');
}
public function postUpdate($id)
{
print_r( $id);
die;
}
}
?>
in getIndex i can return to view customers.blade.php corretcly and i can be create new variable as an new Customers, in view i'm create below form from created new instance from Customers:
{{ Form::model($customers,array('route' => array('customers.update', $customers->id))) }}
...
{{ Form::submit('UPDATE', array('class'=>'btn btn-default btn-default-small') ) }}
{{ Form::close() }}
now i want to send form values to controler, but after send i get this error:
ERROR:
Missing argument 1 for customersController::postUpdate()
form in view must be like with this code :
{{ Form::model($customers,array('route' => array('customers.update', $customers->id))) }}
and your Form::text must be like with:
{{ Form::text('name', $customers->name, array('class'=>'form-control rtl' ) ) }}
Route:
Route::controller(
'customers', 'customersController',
array(
'getIndex' => 'customers.index',
'postUpdate' => 'customers.update'
)
);
now in controller you can try this code to detect form is update or insert
public function postUpdate()
{
if (Input::get('id')) {
$customer = Customers::find(Input::get('id'));
} else {
$customer = new Customers;
}
...
...
...
}
My routes.php excerpt:
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function() {
Route::resource('posts', 'PostsController', [
'except' => ['show']
]);
Route::delete('posts/trash', [
'as' => 'posts.trash.empty',
'uses' => 'PostsController#emptyTrash'
]);
});
My PostsController.php excerpt:
/**
* DELETE /admin/posts/{id}
*/
public function destroy($id)
{
// code
}
/**
* DELETE /admin/posts/trash
*/
public function emptyTrash()
{
// code
}
The problem is that Laravel confuses the 'trash' string in a DELETE /admin/posts/trash request as an {id} parameter. As a consequence, the destroy() method is called instead of emptyTrash(). Why and What can I do for this?
Firstly, order matters. Laravel will search the routes for a match in the order you register them. As you figured out, Laravel will take trash as an id and therefore the URI matches the resource route. Since that route is registered before your additional one, it will use the resource route.
The simplest fix is to just change that order:
Route::delete('posts/trash', [
'as' => 'posts.trash.empty',
'uses' => 'PostsController#emptyTrash'
]);
Route::resource('posts', 'PostsController', [
'except' => ['show']
]);
If you don't like that you can try to limit the parameter for your resource route to numbers only. Unfortunately you can't just add a ->where() to the resource route like you could with others.
Instead you have to define a global pattern for the route parameter. The route parameter Route::resource chooses is the resource name (in snake_case).
So this should work for you:
Route::pattern('posts', '[0-9]+');
Somewhere in your view, you should have a button or a link for actually deleting the post. The view should look something like this:
#section('content')
<div class="panel panel-default">
<div class="panel-heading clearfix">
<b>{{ $post->post_name . ' (id:' . $post->post_id . ')' }}</b><br />
<b> {{ link_to_route('overview', 'Go Back To Post List') }} </b>
<div class="pull-right">
// FORM FOR DELETING POST
{{ Form::open(array('route' => array('delete_post', $post->post_id))) }}
{{ link_to_route('edit_post', 'Edit Post', array('id' => $post->post_id), array('class' => 'post_img_button_edit')) }}
{{ Form::hidden('_method', 'DELETE') }}
{{ Form::submit('Delete Post', array('class' => 'post_img_button_delete')) }}
{{ Form::close() }}
</div>
<div class="pull-right">
// FORM FOR EMPTYING TRASH
{{ Form::open(array('route' => 'empty_trash')) }}
{{ Form::hidden('_method', 'DELETE') }}
{{ Form::submit('Empty Trash', array('class' => 'post_img_button_delete')) }}
{{ Form::close() }}
</div>
</div>
/* Additional HTML code within view */
Your controller should be similar to this:
public function destroy($id)
{
$this->post->delete($id);
return \Redirect::route('overview');
}
public function emptyTrash()
{
// code for collecting and emptying Trash
}
And your routes should look similar to this:
Route::delete('admin_posts/admin_posts/{id}/destroy', array('as'=>'delete_post', 'uses'=>'PostsController#destroy'));
Route::delete('posts/trash', array('as'=>'empty_trash', 'uses'=>'PostsController#emptyTrash'));
The name of your route for actually deleting posts be 'delete_post'.
The name of your route for emptying your trash will be empty_trash
Basically you're explicitly defining your routes so that you'll avoid less ambiguity and Laravel will know which routes to take. Hopefully this information will help!
I have built a simple application laravel 4. I have scaffolding setup for adding posts which seems to be working fine. I have setup Stapler and image uploading package. When I setup to use single image uploads its pretty good and it works a charm. I recently looked at the docs here
It states that you can do multiple uploads so I went about doing it as explained in the docs. Here are my coded pages:
Post.php model:
<?php
class Post extends Eloquent {
use Codesleeve\Stapler\Stapler;
protected $guarded = array();
// A user has many profile pictures.
public function galleryImages(){
return $this->hasMany('GalleryImage');
}
public static $rules = array(
'title' => 'required',
'body' => 'required'
);
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('picture', [
'styles' => [
'thumbnail' => '100x100',
'large' => '300x300'
],
// 'url' => '/system/:attachment/:id_partition/:style/:filename',
'default_url' => '/:attachment/:style/missing.jpg'
]);
parent::__construct($attributes);
}
}
PostsController.php
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
$input = Input::all();
$validation = Validator::make($input, Post::$rules);
if ($validation->passes())
{
$this->post->create($input);
return Redirect::route('posts.index');
}
$post = Post::create(['picture' => Input::file('picture')]);
foreach(Input::file('photos') as $photo)
{
$galleryImage = new GalleryImage();
$galleryImage->photo = $photo;
$user->galleryImages()->save($galleryImage);
}
return Redirect::route('posts.create')
->withInput()
->withErrors($validation)
->with('message', 'There were validation errors.');
}
This has save functions and other functions inside it too.
GalleryImage.php gallery image model to use in the post controller
<?php
class GalleryImage extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('photo', [
'styles' => [
'thumbnail' => '300x300#'
]
]);
parent::__construct($attributes);
}
// A gallery image belongs to a post.
public function post(){
return $this->belongsTo('Post');
}
}
My create.blade.php template to post the post itself
#extends('layouts.scaffold')
#section('main')
<h1>Create Post</h1>
{{ Form::open(array('route' => 'posts.store', 'files' => true)) }}
<ul>
<li>
{{ Form::label('title', 'Title:') }}
{{ Form::text('title') }}
</li>
<li>
{{ Form::label('body', 'Body:') }}
{{ Form::textarea('body') }}
</li>
<li>
{{ Form::file('picture') }}
</li>
<li>
{{ Form::file( 'photo[]', ['multiple' => true] ) }}
</li>
<li>
{{ Form::submit('Submit', array('class' => 'btn btn-info')) }}
</ul>
{{ Form::close() }}
#if ($errors->any())
<ul>
{{ implode('', $errors->all('<li class="error">:message</li>')) }}
</ul>
#endif
#stop
When I post the form with a single images attached its fine and saves to the db and it works a treat but when I save it with multiple image uploads I get this error:
ErrorException
preg_replace(): Parameter mismatch, pattern is a string while replacement is an array
The full stack trace is here in my gist of the files
Can anyone point out to me why this error happens. From my research its creating a multidimensional array that needs flattening I think but I am unsure if this is true.
I have been banging my head against a brick wall with this for ages.
Problem is when your submitting multiple images it becomes an array of pictures instead of a single string. So its trying to save an array to the database instead of a string which its expecting. If you make it so your photo variable is a json_encoded array of pictures then you should be able to save them.
Hope this helps.
I cant figure out what I am missing. I am trying to have a form submit to a controller method through a named route with all of its input and image->id as a parameter. I keep getting a notfoundhttpexception. If I remove /{$id} from the route declaration I get a missing parameter for controller action error. Here is the code:
The route
Route::post('images/toalbum/{$id}', array('as' => 'imgToAlbum', 'uses' => 'ImagesController#addImageToAlbums'));
routes.php
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/
Route::get('/', array('as' => 'home', function()
{
return View::make('layouts.default');
}));
Route::get('users/login', 'UsersController#getLogin');
Route::get('users/logout', 'UsersController#getLogout');
Route::post('users/login', 'UsersController#postLogin');
Route::resource('users', 'UsersController');
Route::resource('images', 'ImagesController');
//routes related to images
Route::post('images/toalbum/{$id}', array('as' => 'imgToAlbum', 'uses' => 'ImagesController#addImageToAlbums'));
Route::resource('videos', 'VideosController');
Route::resource('albums', 'AlbumsController');
view that's submitting the form:
#extends('layouts.default')
#section('content')
<?php
$albumarray = array(null => '');
?>
{{ HTML::image($image['s3Url'], $image['altText']) }}
<p>
Title:{{ $image['caption'] }}</br>
Alt-Text: {{ $image['altText'] }}</br>
Description: {{ $image['description'] }}</br>
</p>
{{ Form::open(array('route' => array('imgToAlbum', $image['id']), 'method' => 'post')); }}
#foreach ($albums as $album)
<?php
array_push ($albumarray, array($album['id'] => $album['caption']));
?>
#endforeach
{{ Form::label('Add image to album?') }}
{{ Form::select('album', $albumarray) }}</br>
{{ Form::submit('Add to Album')}}
{{Form::close();}}
<?php
echo $albums;
?>
#stop
#section('footer')
#stop
controller:
<?php
class ImagesController extends BaseController
{
protected $image;
public function __construct(Image $image)
{
$this->image = $image;
}
// add image to album
public function addImageToAlbums($id)
{
dd($album = Input::all());
$image = $this->where('id', '=', $id);
$image->albumId = $album;
$this->image->save();
/*return Redirect::route('image.show', $this->image->id)
->with('message', 'Your image was added to the album');*/
}
}
Maybe this will help someone in the future so instead of deleting here is the answer. removing the $ from images/toalbum/{$id} in the route declaration has resolved the problem.