I am working with laravel, right now, i am making an user registry Form, i am relating the state and its cities, so, i need to change a select field values according the state that user chooses.
I have something in the form:
{{ Form::select('city', $city, array('id', 'city')}}
If i use the {{Form::select}} fields in conventional way it charges all the cities from one state, so, when the user select a state, it must change the list of cities in the select field.
I searched but i didn't find any. How can i do that?
thanks.
You can use ajax with jQuery.
In your view set an event when the state change, like this:
$(document).on('change', '#state_id', function (e) {
// empty the select with previous cities if we have.
$('#cities').empty();
$.ajax({
type: "POST",
dataType: "json",
// actions is a controller
// cities is a method of actions controller
url : "{{ URL::to('actions/cities') }}",
//here we set the data for the post based in our form
data : $('#MyFormID').serialize(),
success:function(data){
if(data.error === 0 ){ // all was ok
for (var i = 0; i < data.cities.length; i++) {
$('#cities').append("<option value='"+data.cities[i].id+"'>"+data.cities[i].city_name+"</option>")
}
}else{
alert(data);
}
},
timeout:10000
});
});
actions/cities controller
//remember, this is a post method
public function postCities(){
// validate
$validator = Validator::make(Input::all(),
array(
'state_id' => 'required|integer'
));
if ($validator->fails()) {
return Response::json(array('error' => 1, 'message' => 'State is required'));
}
//City is your model, I assumes that you pkey is ID and the city name is city_name and your fkey is state_id
$cities = City::where('state_id', '=', Input::get('state_id'))->get();
return Response::json(array('error' => 0, 'cities' => $cities));
}
public function getCities($province_id)
{
$cities = Cities::where('province_id', '=', $province_id)->get(['id', 'name']);
return Response::json(array('error' => 0, 'cities' => $cities));
}
You might want to check a sample vue component that ships with my package Laravel Cities that performs exactly what you are trying to build.
This is a simple package that allows you seed localy all the cities of any country on the world (provided by geonames.org) and perform any query with the provided Eloquent model. It exposes an HTTP API and a vue component that allows you to select any city through a series of steps.
You can insert it in your forms like any other input field:
<form action="post-url" method="POST">
<geo-select></geo-select>
<!-- Add more form fields here... -->
<input type="submit">
</form>
With the provided Eloquent model You can perform queries like this:
// Get the States of USA in aplhabetic order
Geo::getCountry('US')
->children()
->orderBy('name')
->get();
Sorry, no demo yet, but you can check some sceenshots on the github page...
Related
I have ProjectController that fetches data from the database and passes it to a blade file. One of the data items is the project_id. I want to pass the project _id from the blade file to another controller BidController.
ProjectController.php
public function show($id)
{
$project = Project::find($id);
return view('project.show',['project'=>$project]);
}
show.blade.php
div class="card-header">PROJECT <p>{!! $project->id !!}</p></div>
BidController.php
public function store(Request $request)
{
$bid = new Bid;
$bid->project_id = $project_id;
dd($project_id);
}
The dd(); does not output the project_id. I need help in passing the project_id from the blade file to the BidController method.
You can't directly set a model's id like you're doing in the line $bid->id = $project_id;. Are you trying to set up a relationship? That should be more like $bid->project_id = $request->project_id;.
Blade templates can't really pass things back to controllers, once they're in the browser your app is sort-of finished running. You need to create an HTML link/request on the page (like a form post request) that'll request the next thing from your app when the user clicks it.
If you want to create a button that creates a new bid for an existing project, you could do something like set up a form with a hidden field of 'project_id' that posts back to '/bids' which goes to the route 'bids.store'. You'll find 'project_id' under $request->project-id'.
You can send an AJAX request from Javascript:
View
<script type="text/javascript">
var project_id= {!! json_encode($project->id) !!}
$.ajax({
type: 'POST',
url: url, //Your bidController route
data: {project_id: project_id},
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown)
},
success: function()
{
console.log('successful')
}
});
</script>
This will sent the data to the controller asynchronously so the user experience doesn't get affected.
One extra point: In your Bid controller, as project_id is coming from the request, you'll have to use:
$bid->id = $request->project_id;
I hope it helps!
PS: I'm using JQuery for this, so you'll have to include it if you don't already have.
I think this will solve your problem :
ProjectController.php
public function show($id)
{
$project = Project::findOrFail($id);
return view('project.show',compact('project');
}
web.php
Route::post('/bids/store/{id}' , 'BidController#store')->name('bids.store');
show.blade.php
div class="card-header">PROJECT <p>{{$project->id}}</p></div>
<form action="{{route('bids.store', $project->id)}}" method="post">
BidController.php
public function store(Request $request, $id)
{
$bid = new Bid;
$bid->id = $id;
$bid->save();
dd($id);
}
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
I am trying to fetch the list of city_name (column) from my table Cities and display that list into my dropdown
I write the following code in my controller method
namespace App\Controller;
use App\Controller\AppController;
class PrimeUsersController extends AppController
{
public function initialize()
{
parent::initialize();
$this->viewBuilder()->setlayout('primewishsLayout');
$this->loadModel("Cities");
$this->loadModel("States");
$this->loadModel("Users");
}
public function addnew()
{
// $this->autoRender=false;
$this->set('title',"Add User/Company");
$digits_needed=10;
$random_number=''; // set up a blank string
$count=0;
while ( $count < $digits_needed )
{
$random_digit = mt_rand(0, 9);
$random_number .= $random_digit;
$count++;
}
$this->set("rendomReg",$random_number);
// $view=$this->States->find()->toArray();
// print_r($view);
// city list
$fieds = array('Cities.city_name');
$city = $this->Cities->find()->select(['city_name'])->enableHydration(false)->toList();
// print_r($city);die;
$this->set(compact('city'));
}
}
and this is my dropdown where I want to show my item list in addnew.ctp
<div class="col-md-3 pl-1">
<div class="form-group">
<label>City:</label>
<?php
echo $this->Form->control('City',array(
'options' => $city,
'value'=>$option,
'required'=>'required',
'class'=>'form-control',
'label'=>false,
'default' => $option['select']
));
?>
</div>
</div>
I am able to fetch the list but when I click on dropdown the list display like this:-
1
Kanpur
2
Lucknow
3
Delhi
please help me out..
According to Cakephp
CakePHP provides a simple to use method for generating ‘lists’ of
data. It is often useful to generate an associative array of data from your application’s data. For example, this is very useful when creating elements.
So to get the list of cities you can use list in your find query. This will give you an associative array of id and city name from your cities table.
PrimeUsersController.php
$city = $this->Cities->find('list')->find('list', [
'keyField' => 'id', // specify column name that you used used as city id in cities table
'valueField' => 'city_name' // specify column name that you used used as city name in cities table
])->toArray();
$this->set(compact('city'));
addnew.ctp
$this->Form->select(
'city',
$city,
['required'=>'required',
'class'=>'form-control',
'label'=>false,
'empty' => 'Select City']
);
Cakephp -> Retrieving Data & Results Sets -> Finding Key/Value Pairs
Hope this will help!
Try something like this:
$this->Form->select(
'city',
$city,
['required'=>'required',
'class'=>'form-control',
'label'=>false,
'default' => ':Select:']
);
More instructions: https://book.cakephp.org/3.0/en/views/helpers/form.html#common-options-for-specific-controls
I'm new to laravel and I want to get data from database and show it on Alert using ajax
My Route:
Route::get('getforajax/{id}','Home#getforajax');
My Controller:
public function getforajax ($id)
{
$result=DB::select('select * from employees where empid =?',[$id]);
return $result;
}
my View:
$('#empid1').keyup(function() {
$.ajax({
url: 'getforajax/3',
type: 'GET',
data: data,
dataType: 'json',
success: function (data) {
alert(data.empid);
}
});
});
You can return json from the controller.
return response()->json($result, 200);
However, the result will be an array of al the resultant rows from the query. So even if you are expecting a single result from query, it is still going to give yo an array of single entry.
[
[
id => something,
name => something
]
]
Also, you can improve it as following :
In your javacript you need to do :
data[0].empId
However, you need to make sure the data is there. Use eloquent models for loading entry from Id :
$result = Employee::findOrFail($employeeid);
And then you do directly do :
alert(data.empid);
You should try this:
use App\Employee; //employee table's model
public function getforajax ($id)
{
$result=Employee::find($id);
return $result;
}
I have a view which will show the list important tasks from database. I have a function in controller which returns the collection of data to the view.
My controller function is
public function list()
{
$tasks= Task::where('category','1')->get();
//category is 1 when the task is important
return view('important', compact('tasks'));
}
My view is like
<ul>
#foreach ($tasks as $task)
<li> {{$task->body}}</li>
#endforeach
</ul>
What I want to essentially do is to call the list function whenever a new important task is added into the database. How can I do that?
in your web.php
Route::get('/tasks','TasksController#list')->name('get_tasks');
inside your controller :
use Illuminate\Http\Request;
public function list(Request $request)
{
$tasks= Task::where('category','1')->get();
if($request->ajax()){
return response()->json(array('tasks'=>$tasks));
}
return view('important', compact('tasks'));
}
inside your blade view :
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
setInterval(function(){
$.ajax({
url:'/tasks',
type:'GET',
dataType:'json',
success:function(response){
if(response.tasks.length>0){
var tasks ='';
for(var i=0;i<response.tasks.length;i++){
tasks=tasks+'<li>'+response.tasks[i]['body']+'</li>';
}
$('#tasklist').empty();
$('#tasklist').append(tasks);
}
},error:function(err){
}
})
}, 5000);
});
</script>
<ul id="tasklist">
#foreach ($tasks as $task)
<li> {{$task->body}}</li>
#endforeach
</ul>
To achieve this kind of setup you may use Pusher or any other similar provider, once you signup on pusher you can send 200k notifications per day for free, you can check the limits after login to pusher. Before we proceed please install pusher's official php package
composer require pusher/pusher-php-server
From your pusher dashboard obtain app_id, key, secret and cluster now in your controller/model where you are inserting the data in database add the following code
//You will get cluster name from pusher.com replace it below
$options = ['cluster' => 'mt1', 'encrypted' => true];
//Replace your key, app_id and secret in the following lines
$pusher = new Pusher(
'key',
'secret',
'app_id',
$options
);
//this could be a single line of message or a json encoded array, in your case you want to pass some data to display in table I assume you have an array
$message= json_encode(['name' => 'John doe', 'age' => 42, 'etc' => 'etc']);
//Send a message to users channel with an event name of users-list. Please mind this channel name and event name could be anything but it should match that with your view
$pusher->trigger('users', 'users-list', $message);
Now in your view before the </body> tag paste the following code
<!-- Incldue Pusher Js -->
<script src="https://js.pusher.com/4.2/pusher.min.js"></script>
<script>
//Remember to replace key and cluster with the credentials that you have got from pusher.
var pusher = new Pusher('key', {
cluster: 'mt1',
encrypted: true
});
//In case you have decided to use a different channel and event name in your controller then change it here to match with the one that you have used
var channel = pusher.subscribe('users');
channel.bind('users-list', function(message) {
//if you will console.log(message) at this point you will see the data
//that was sent from your controller is available here please consume as you may like
alert(message);
});
</script>