Validate the array inputs value to already selected or not - laravel

I want to validate the array inputs value to already selected or not. In my case, I am using Laravel Livewire and I have dynamic inputs such as I can add new options like Size, Color. But I do not want to select the same value in two inputs like the select size in two inputs. Basically, If select the same value in the second input, I want to show it already selected.
Below code livewire controller,
public $i = -1;
public $inputs = [];
public $options = ['Size', 'Color', 'Material', 'Style'];
public $option_name;
function rules()
{
$rules = [];
if ($this->inputs) {
foreach ($this->inputs as $key => $val) {
$rules['option_name.' . $val] = ['required'];
}
return $rules;
}
}
public function addLine($i)
{
$i = $i + 1;
$this->i = $i;
array_push($this->inputs, $i);
}
public function updated($propertyName)
{
if ($this->inputs) {
$this->validateOnly($propertyName);
}
}
Below code livewire view code,
#forelse ($inputs as $key => $value)
<x-native-select label="Option name" :options="$options" wire:model="option_name.{{ $value }}"/> // I am using livewire-wireui
#empty
#endforelse
<a wire:click="addLine({{ $i }})" class="mt-4 text-sm cursor-pointer">
+ Add another option
</a>
Any idea how to validate this?

Try this and let me see how it goes.
public function updatedOptionName($selectedOption) {
//You can use laravel collection filter as well depending on how commplicated you want it
$this->options = array_filter($this->options, function ($value) {
return $value != $selectedOption;
}, ARRAY_FILTER_USE_BOTH));
}
The above function would filter out the selected option so that the option is not available when it is already selected. It might be overkill and subject to improvement from the community. All reviews are welcome. One thing to note is that you might want a sort of reset method in case the user decides to start all over again. Something along the lines of public $originalOptions that you would want to set on mount and then a reset function that assigns this->options to it. Let me know if it works.
More info on those functions Lifecycle hooks

Related

Livewire generating a collection on mount, but an array on refresh

I have a (relatively) simple Livewire controller which, on mount() generates a collection of games, grouped by their start dates, and assigns it to the $games public property.
public $games;
protected $rules = [];
...
public function mount() {
$now = Carbon::now();
$games = Game::where('start', '>', $now)->orderBy('start', 'ASC')->get();
$games = $games->groupBy(function($item) {
return $item->start->format("Y-m-d H:i:s");
})->collect();
$this->games = $games;
}
The corresponding component then loops through the dates, outputs the date, and then sends the games themselves to a Blade component (irrelevant styling removed):
#foreach($games as $date => $thegames)
<div>
{{ \Carbon\Carbon::createFromFormat("Y-m-d H:i:s", $date)->format("l jS \of F Y - g:i A") }}
</div>
<div>
<x-individual.game :allgames="$thegames" :user="Auth::user()"></x-individual.game>
</div>
#endforeach
The Blade component then loops through the games that it's been given and renders each of them (simplified below) :
#foreach($allgames as $game)
<div>
<div>
<h3>
{{ $game->game->name }}
</h3>
</div>
</div>
#endforeach
Within that component (not shown) are wire:click buttons which may add a person to the game, or remove them. That, in turn, fires the refresh() function of the original Livewire component, which is identical to the mount() function save that it emits the refreshComponent event at the end :
public function refreshThis() {
$now = Carbon::now();
$games = Game::where('start', '>', $now)->get();
$games = $games->groupBy(function($item) {
return $item->start->format("Y-m-d");
})->collect();
$this->games = $games;
$this->emit('refreshComponent');
}
That's where the problem starts. Rather than re-render the component, as it should, it generates an error of "Attempt to read property "game" on array" within the blade component :
{{ $game->game->name }}
and sure enough, at that point, $game is now an array, not an Eloquent object (or whatever it was first time around).
If I manually refresh the page, the changes are shown without issue. But why is it issuing me an array on refreshing, and (more importantly) how can I stop it?
You could add the $games to the render method instead and it will refresh the data:
public function render()
{
$now = Carbon::now();
$games = Game::where('start', '>', $now)->orderBy('start', 'ASC')->get();
$games = $games->groupBy(function($item) {
return $item->start->format("Y-m-d H:i:s");
})->collect();
return view('livewire.your_component_view', [
'games' => $games
]);
}
Then refresh the component (in your main component):
public function refreshThis() {
$this->render();
}
If you are calling refresh from a child component you can call it form there:
Child component:
$this->emit('refreshThis');

Why does the old() method not work in Laravel Blade?

My environment is Laravel 6.0 with PHP 7.3. I want to show the old search value in the text field. However, the old() method is not working. After searching, the old value of the search disappeared. Why isn't the old value displayed? I researched that in most cases, you can use redirect()->withInput() but I don't want to use redirect(). I would prefer to use the view(). method
Controller
class ClientController extends Controller
{
public function index()
{
$clients = Client::orderBy('id', 'asc')->paginate(Client::PAGINATE_NUMBER);
return view('auth.client.index', compact('clients'));
}
public function search()
{
$clientID = $request->input('clientID');
$status = $request->input('status');
$nameKana = $request->input('nameKana');
$registerStartDate = $request->input('registerStartDate');
$registerEndDate = $request->input('registerEndDate');
$query = Client::query();
if (isset($clientID)) {
$query->where('id', $clientID);
}
if ($status != "default") {
$query->where('status', (int) $status);
}
if (isset($nameKana)) {
$query->where('nameKana', 'LIKE', '%'.$nameKana.'%');
}
if (isset($registerStartDate)) {
$query->whereDate('registerDate', '>=', $registerStartDate);
}
if (isset($registerEndDate)) {
$query->whereDate('registerDate', '<=', $registerEndDate);
}
$clients = $query->paginate(Client::PAGINATE_NUMBER);
return view('auth.client.index', compact('clients'));
}
}
Routes
Route::get('/', 'ClientController#index')->name('client.index');
Route::get('/search', 'ClientController#search')->name('client.search');
You just need to pass the variables back to the view:
In Controller:
public function search(Request $request){
$clientID = $request->input('clientID');
$status = $request->input('status');
$nameKana = $request->input('nameKana');
$registerStartDate = $request->input('registerStartDate');
$registerEndDate = $request->input('registerEndDate');
...
return view('auth.client.index', compact('clients', 'clientID', 'status', 'nameKana', 'registerStartDate', 'registerEndDate'));
}
Then, in your index, just do an isset() check on the variables:
In index.blade.php:
<input name="clientID" value="{{ isset($clientID) ? $clientID : '' }}"/>
<input name="status" value="{{ isset($status) ? $status : '' }}"/>
<input name="nameKana" value="{{ isset($nameKana) ? $nameKana : '' }}"/>
...
Since you're returning the same view in both functions, but only passing the variables on one of them, you need to use isset() to ensure the variables exist before trying to use them as the value() attribute on your inputs.
Also, make sure you have Request $request in your method, public function search(Request $request){ ... } (see above) so that $request->input() is accessible.
Change the way you load your view and pass in the array as argument.
// Example:
// Create a newarray with new and old data
$dataSet = array (
'clients' => $query->paginate(Client::PAGINATE_NUMBER),
// OLD DATA
'clientID' => $clientID,
'status' => $status,
'nameKana' => $nameKana,
'registerStartDate' => $registerStartDate,
'registerEndDate' => $registerEndDate
);
// sent dataset
return view('auth.client.index', $dataSet);
Then you can access them in your view as variables $registerStartDate but better to check if it exists first using the isset() method.
example <input type='text' value='#if(isset($registerStartDate)) {{registerStartDate}} #endif />

How to create a search that uses barcode

I'm creating a search system for a point of sale that uses barcodes to search for products. When a user scans a barcode, the product with the corresponding barcode gets added to the cart. I pass the barcode to the controller using Ajax. The problem is, the resulting query is running twice doubling the order quantity when the product gets added to the cart. I don't know why this is happening.
View/Search Bar
<div class="frmSearch">
<input type="text" id="search" name="search" class="form-control" placeholder="Type Product Name..."
onmouseover="this.focus();"/>
</div>
<script type="text/javascript">
$('#search').on('keyup', function () {
$value = $(this).val();
$.ajax({
type: 'get',
url: '{{URL::to('search')}}',
data: {'search': $value},
success: function (data) {
window.location.href = "/addsale/" + data;
}
});
});
</script>
Controller
public function search(Request $request)
{
if ($request->ajax()) {
$raws = DB::table('items_masters')->where('bcode', '=', $request->search)->first();
if ($raws) {
$output = $product->id;
}
return Response($output);
}
}
Method to add a product to the cart
public function add($id)
{
$userid = Auth::user()->id;
$shop = Auth::user()->shop_id;
$product_id = $id;
$tdo = item_quantity::getQuery('item_quantities')->where([
['shop_id', '=', $shop],
['item_id', '=', $product_id]
])->get();
foreach ($tdo as $key => $tad) {
$product_quantity = $tad->quantity;
}
if (empty($product_quantity)) {
session()->flash('message', 'Item Not In Your Shop');
return redirect('/sales_area');
} elseif ($product_quantity <= 0) {
session()->flash('message', 'Item Out Of Stock');
return redirect('/sales_area');
} else {
$todo = tblcart::getQuery('tblcarts')->where([
['product_id', '=', $id], ['shop_id', '=', $shop],
['member_id', '=', $uid]
])->get();
foreach ($todo as $key => $tada) {
$cart_id = $tada->id;
}
if (empty($cart_id)) {
$tem = new tblcart;
$tem->product_id = $product_id;
$tem->quantity = 1;
$tem->shop_id = $shop;
$tem->member_id = $userid;
$tem->save();
return redirect('/sales_area');
} else {
$tem = tblcart::find($cid);
$tem->quantity = $tem->quantity + 1;
$tem->save();
return redirect('/sales_area');
}
}
}
Currently, when a user adds a product to the cart, the order quantity is doubled, so instead of one, he gets two. If the user adds the same product again, he gets four instead of two. How can I sort this out?
Looks like perhaps a timing problem, depending on if the add method is called directly from the search. With keyup, you run a possible risk of triggering the search function at least once, and possibly more than once based on the user still typing the product they want even after the original ajax request has been sent based on the previous character typed within the search bar.
Suggestion would be to add a time delay on either the keyup function, or within your search code. Say something like (pseudo code) within the controller
if($timeOfLastTransaction < 30 seconds && $productId == $previousProductId)
// cancel this duplicate
else
set $timeOfLastTransaction
set $previousProductId
I'm still not sure what's calling the add() method, and this would be a good start for bug hunting the specific doubling-up error.
But, looking at that code in the add() method, there are a number of things that you might clean slightly -- and may resolve your issue. Suggest naming the $id variable $product_id directly in the method's params instead of renaming it in the top part -- you use two different vars for the same thing in multiple places, and it is a little confusing.
A little bigger issue is that you are potentially re-assigning the same variable in several places after pulling a collection from the database:
$tdo = item_quantity::getQuery('item_quantities')->where( [['shop_id', '=', $shop],
['item_id', '=', $product_id]])->get();
foreach ($tdo as $key => $tad) {
$product_quantity=$tad->quantity;
}
This line and the next DB pull below it both loop through a collection and re-assign / overwrite $product_quantity in this case and $cart_id in the next. Why not use ->first() and skip the loop? I think this might reduce any unforeseen errors as well

Trying to get property 'post_titile' of non-object

This is My Controller.
public function show(Posts $posts)
{
$page = Posts::find($posts->id);
//dd($page);
return view('web_views.index',['page' => $page]);
}
This is my view page
<h4>{{$page->post_titile}}</h4>
It's better to use Route-Model Binding I think.
Your route (if you are using resource route, it's already done):
Route::get('posts/{post}', 'PostController#show); // domain.tld/posts/1
Your method should look like this:
public function show(Post $post)
{
return view('web_views.index',compact('post'));
}
In your view:
<h4>{{ $post->post_titile }}</h4>
May be $posts->id you are passing, has no result in database so you need to check it by using if-statement
public function show(Posts $posts)
{
$page = Posts::find($posts->id);
if($page == null){
$page = ['post_title' => 'Not Available'];
}
return view('web_views.index',['page' => $page]);
}
I believe this error is because of not finding data for an ID into database. So if as per above script will pass the fetched data to view otherwise it will push an item into $page array.

how to extract single data of row id and not other from same column?

how to extract single data of row id and not other from same column in laravel 5.3 and view it on browser. i have tried an example please see this and give me feedback as soon as possible. thanks in advance.
public function index($id)
{
$data = $this->issue->find($id);
if(is_null($data))
{
return abort(404);
}
$data = DB::table('issue')->select('id','return_date')->get();
return view('library.after',['issue'=>$data]);
}
and this is my view
#foreach($issue as $is)
{{'<ID="'.$is->id.'" label="'.$is->return_date.'">' }}<br>
#endforeach
if you want to get only one row then fetch one row from database.
public function index($id)
{
$data = $this->issue->find($id);
if(is_null($data))
{
return abort(404);
}
$data = DB::table('issue')->select('id','return_date')->first();
return view('library.after',['issue'=>$data]);
}
in view
{{'<ID="'.$issue->id.'" label="'.$issue->return_date.'">' }}<br>

Resources