I am using first time laravel livewire in my project. I am trying to create one simple filter option and this filter will trigger from a dropdown. My problem is when a dropdown value change its completely hide my component view.
I am not sure where i am making a mistake in this but i want to know the best way to resolve this.
my code is this Livewire component
<?php
namespace App\Http\Livewire\Frontend\Boat;
use App\Models\Product;
use Livewire\Component;
class Listing extends Component
{
public $filter_option;
// public $message;
public $product;
public function mount()
{
$this->product = Product::where([
'type_id' => 1,
'status' => 1,
])->orderBy('name', 'asc')->get();
}
public function filter_speed()
{
$this->product = Product::where([
'type_id' => 1,
'status' => 1,
])->orderBy('name', 'asc')->get();
}
public function render()
{
return view('livewire.frontend.boat.listing');
}
}
My blade is
<select wire:model="filter_option" class="form-control" wire:change='filter'>
<option value="#">Filter</option>
<option value="speed">Speed</option>
</select>
//or
<button wire:click='filter_speed'>Filter by speed</button> <!-- Simple button click -->
In my opinion in your case its not necessary to use Query on mount().
But If in case of Filter u can use this method:
<?php
// Livewire
namespace App\Http\Livewire\Frontend\Boat;
use App\Models\Product;
use App\View\Components\comment;
use Livewire\Component;
class Listing extends Component
{
public $filter_option;
// public $message;
// public $product;
public $orderBy = 'id';
public $orderType = 'desc';
public function filter_speed()
{
$this->orderBy = 'speed';
// $this->emit('filter_speed');
}
public function render()
{
$product = Product::where([
'type_id' => 1,
'status' => 1,
])
->orderBy($this->orderBy, $this->orderType)
->get();
return view('livewire.frontend.boat.listing', compact('product'));
}
}
<button wire:click.prevent='filter_speed'>Filter by speed</button>
Instant of making many Query make one with custom variable
Related
This is my Livewire component
<?php
namespace App\Http\Livewire\Dashboard;
use App\Models\Post;
use Livewire\Component;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class EditPost extends Component
{
use AuthorizesRequests;
public ?Post $postSingle = null;
protected $rules = [
'postSingle.priority' => 'digits_between:1,5',
];
public function setPriority(Post $postSingle, $priority)
{
$this->authorize('update', $postSingle);
$this->postSingle->priority = $priority;
}
}
In my blade view I have
<button wire:click="setPriority({{ $postSingle->id }}, 4)"></button>
and somewhere else I show the priority with {{ $postSingle->priority }}
The reason why I don't do model property binding directly with wire:model="postSingle.priority" is that I want to run $this->authorize('update', $postSingle);.
What happens with the code below is that if I click the button, $postSingle->priority in the blade view is updated, but the Post record is not updated in my database. What am I missing?
You appear to have overlooked actually saving the record.
public function setPriority(Post $postSingle, $priority)
{
$this->authorize('update', $postSingle);
$this->postSingle->priority = $priority;
// save the record
$this->postSingle->save();
}
I'm not familiar with Vue.js at all, so found a good replacement using Livewire.
The challenge that I've got to solve is to have a user friendly registration on my website using Fortify + Livewire. The registration process is a multistep one and depends on the choices that the user makes it will load the relative fields.
So far I set up the Fortify views by adding in the FortifyServiceProvider.php file the following code:
Fortify::loginView(function () {
return view('auth.login');
});
Fortify::registerView(function () {
return view('auth.register');
});
The auth/login.blade.php view loading the livewire component which is basically a form:
<form action="{{ route('register') }}" method="POST" wire:submit.prevent="submit">
/**
* Here would go the inputs that must be shown depends on what users choice
* (is it an ordinar user or a company)
*/
<button type="submit">Save<button/>
</form>
The multiform challenge would be resolved by adding $step property into the Register.php class:
class RegisterForm extends Component
{
public $step;
public function mount()
{
$this->step = 0;
}
public function submit()
{
if ($this->step < 3) {
$this->step++;
} else {
// pass all the data to the fortify register method
// <-- Here is my trouble!
}
}
}
which will be incremented by passing each of the registration steps ($this->step++).
The most important thing that is quite complicated for me is how to prevent form submission to have the validation + form changes and by the end all the set of the data to pass trough Fortify registration process?
Look at the fortify Controller for register
public function store(Request $request, CreatesNewUsers $creator): RegisterResponse
{
event(new Registered($user = $creator->create($request->all())));
$this->guard->login($user);
return app(RegisterResponse::class);
}
T
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\CreatesNewUsers;
use Livewire\Component;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
public function submit(CreatesNewUsers $creator)
{
event(new Registered($user = $creator->create([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'password_confirmation' => $this->password_confirmation,
])));
Auth::guard()->login($user);
$this->redirect('home');
}
public function render()
{
return view('livewire.register');
}
}
Something like this will work for your use case.
You are still using the fortify Action and Still Firing the Event
The response is to use app container
<?php
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use App\Actions\Fortify\CreateNewUser;
use Livewire\Component;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
public function submit()
{
event(new Registered($user = app(CreateNewUser::class)->create([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'password_confirmation' => $this->password_confirmation,
])));
Auth::guard()->login($user);
$this->redirect('home');
}
public function render()
{
return view('livewire.register');
}
}
The response is to use dependency injection by injecting the Fortify CreateNewUser action in the mounting method of the Livewire component.
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use App\Actions\Fortify\CreateNewUser;
use Livewire\Component;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
protected $creator;
public function mount(CreateNewUser $creator)
{
$this->creator = $creator;
}
public function submit()
{
event(new Registered($user = $this->creator->create([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'password_confirmation' => $this->password_confirmation,
])));
Auth::guard()->login($user);
$this->redirect('home');
}
public function render()
{
return view('livewire.register');
}
}
you can use blade example
#if($step > 3)
<input name="name" type="text">
#endif
I have a problem with some of my routes in Laravel. this my code in web.php file:
Route::group(['namespace' => 'Admin', 'middleware' => ['auth:web']], function () {
Route::get('/admin/audio/create/{audio?}', 'AdminAudioController#create')->name('admin.audioCreate');
Route::get('/admin/article/create/{article?}', 'AdminArticleController#create')->name('admin.articleCreate');
}
and this my link in blade
<i class="fa fa-edit"></i>
<i class="fa fa-edit"></i>
and this are my Controllers:
AdminAudioController
<?php
namespace App\Http\Controllers\Admin;
use App\Article;
use App\Http\Requests\ArticleRequest;
class AdminArticleController extends AdminController
{
public function index()
{
$articleList = Article::where('removed', false)->latest()->paginate(10);
return view('admin.article.archive', compact('articleList'));
}
public function create(Article $article = null)
{
return view('admin.article.create', compact('article'));
}
}
AdminArticleController
<?php
namespace App\Http\Controllers\Admin;
use App\Article;
use App\Http\Requests\ArticleRequest;
class AdminArticleController extends AdminController
{
public function index()
{
$articleList = Article::where('removed', false)->latest()->paginate(10);
return view('admin.article.archive', compact('articleList'));
}
public function create(Article $article = null)
{
return view('admin.article.create', compact('article'));
}
}
but my second link with name "admin.articleCreate" doesn't work and get "404 not found" what should I do?
and this is my article model
class Article extends Model
{
protected $primaryKey = 'articleId';
use Sluggable;
protected $fillable = [
'title',
'subTitle1', 'subTitle2',
'image',
'description',
'body',
'enable',
];
protected $casts = [
'image' => 'array'
];
/**
* Return the sluggable configuration array for this model.
*
* #return array
*/
public function sluggable(): array
{
return [
'slug' => [
'source' => 'title'
]
];
}
public function getRouteKeyName()
{
return 'slug';
}
}
When you call the method create(Article $article = null) on your controller, Laravel uses Model Binding to resolve your model and the model binding uses the method you have added to your model
public function getRouteKeyName()
{
return 'slug'; // by default it will be $primaryKey which is 'id'
}
In short, Laravel will try to use slug to find your model while your giving him articleId
So to fix it you have few options
Using the slug in the URL (the one I would recommend)
// blade.php
<i class="fa fa-edit"></i>
Using the primary articleId in the URL
// blade.php
<i class="fa fa-edit"></i>
// Article.php.php
public function getRouteKeyName()
{
return 'articleId';
}
Using a query
// blade.php
<i class="fa fa-edit"></i>
//Controller.php
public function create($article = null)
{
$article = Article::where('YOUR_FIELD', $article)->firstOrFail();
return view('admin.article.create', compact('article'));
}
you have code
return view('admin.article.create', compact('$article'));
but need
return view('admin.article.create', compact('article'));
I can see you have mentioned $article in side compact.
Can you please check once, I think the create method should look like this:
public function create(Article $article = null)
{
return view('admin.article.create', compact('article'));
}
I have upgraded the laravel excel library (Maatswebsite) from 2x to 3.1 (running Laravel 5.6/php 7.1) and trying to make my old data work (download exported file) and cannot work out how to pass my $data (which is an array from a foreach DB query (not eloquent) in controller) to the UsersExport.php class...
If I manually create a test collection (mirroring my $data array) in the class:
return collect([
[
'name' => 'F Name 1',
'surname' => 'Last Name 1',
'email' => 'Email 1'
'date_completed' => 'xx/xx/xx'
],
[
'name' => 'F Name 2',
'surname' => 'Last Name 2',
'email' => 'Email 2',
'date_completed' => 'xx/xx/xx'
]
]);
the above works perfect and the file is created and downloads when I run:
return Excel::download(new UsersExport, 'Test.xlsx');
But I want to pass my array ($data) from the controller to the class and not sure HOW I do this... I am trying to get something like this to work:
return Excel::download(new UsersExport($data), 'Test.xlsx');
From reading the specific posts I could find, I believe I need to create a constructor in the Class to accept my $data - but not sure how, and how to return that data if I succeed in my class accepting the data etc... Is the FromCollection the right option?
private $data;
public function __construct($data)
{
$this->data = $data;
}
Appreciate any assistance.... Thanks in advance.
Your approach is right. then use the collection() function to return that data.
private $data;
public function __construct($data)
{
$this->data = $data;
}
public function collection()
{
return $this->data;
}
if you want passing param data to class you use construct.
Example Controller:
<?php
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\CustomerinvoiceExport;
use App\Model\OrderInvoiceList;
use Illuminate\Http\Request;
class CustomerInvoiceController extends Controller
{
public function index(Request $request)
{
if ($request->has('start_date')) {
$start_date = $request->start_date;
} else {
$date_now = Carbon::now();
$start_date = $date_now->toDateString();
}
if ($request->has('end_date')) {
$end_date = $request->end_date;
} else {
$date_now = Carbon::now();
$end_date = $date_now->toDateString();
}
$customer_invs = OrderInvoiceList::customer_invoice($start_date, $end_date);
return Excel::download(new CustomerinvoiceExport($customer_invs), 'Customer_Invoice_Report.xlsx');
}
}
}
Class Export
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
class CustomerinvoiceExport implements FromCollection
{
protected $customer_invs;
/**
* Customer Invoice Report
*/
public function __construct($customer_invs)
{
$this->customer_invs = $customer_invs;
}
/**
* #return invoice_list
*/
public function collection(): array
{
$invoice_list = $this->invoice_list;
...........your logic here....
}
}
I need all the invitations in show. This I want to do under a company when that company is selected must invite come forth only now I get the error.
Method invite does not exist (Im very new in Vue.js)
Overview.vue code
<v-container fluid grid-list-md>
v-layout v-if="query === 'invites'" align-space-between justify-center row fill-height wrap>
<span v-for="invite in invites" :key="invite.id">{{ invite.email }}</span>
</v-layout>
InviteController index:
public function index( Manager $fractal, InviteTransformer $inviteTransformer ) {
Auth::user()->authorizeRoles( 'user.view' );
// Get all companies
$companies = Auth::user()->companies()->get();
$invites = $companies->invites()->get();
// Restructure for output
$collection = new Collection( $invites, $inviteTransformer );
$data = $fractal->createData( $collection )->toArray();
return $this->respond( $data );
}
ComapnyModel:
<?php
namespace App\Models\Manage;
use Illuminate\Database\Eloquent\Model;
class Company extends Model {
// This table does not have timestamps
public $timestamps = false;
protected $fillable = [ 'name' ];
public function users() {
return $this->hasMany( 'App\Models\Manage\User' )->orderBy('lastname')->orderBy('firstname')->orderBy('id');
}
public function userIds() {
return $this->users()->pluck('id');
}
public function admins() {
return $this->belongsToMany( 'App\Models\Manage\User' )->orderBy('lastname')->orderBy('firstname')->orderBy('id');
}
public function adminIds() {
return $this->admins()->pluck('id');
}
public function invites() {
return $this->hasMany( 'App\Models\Manage\Invite' )->orderBy('email')->orderBy('id');
}
}
Ficed by myself i needed to remove ->get();