Laravel 5.1 Ajax to get html from Blade View - ajax

I have a myitems($filter) method in a ItemsController that loads the myitems.blade view.
The view has list of items as label and text box to get number of items ($items is passed from myitems method to myitems view and there is a model form binding on items model as well)
I have a select box that has options 1. All, 2. Expired and 3.New
When I change the selection I want to have get new $items from the controller and recreate the form with new items list.
I am using using jquery to alert that the selection is changed. but I am not able to figure out how will I be able to call myitems($filter) from ajax and redirect to create the items.blade page.

Route
//Note the ? in parameter, it says parameter is optional
Route::get('/myitems/{filter?}',
['as' => 'myitems.list', 'uses' => 'ItemController#myitems']
);
Controller
...
public function myitems(Request $request, $filter = null)
{
if (empty($filter)) $filter=1;
$items = Item::where('item_type', $filter)->get();
// if ajax call just return the partial that displays the list
if ($request->ajax()) {
return view('_itemlist', compact('items'));
}
// passed as options to input select
$filters= [
'All' => '0',
'New' => '1',
'Expired' => '2'
];
return view('itempagewith_defaultitemlist', compact('items','filters'));
}
...
View
view itempagewith_defaultitemlist.blade.php
<div class="container">
{!! Form::model($myitems, ['route' => 'myitems.list', 'class'=>'form-horizontal', 'files' => true]) !!}
<div id="filterselectbox">
<div class="form-group">
{!!Form::label('filterselectbox','*Filter:',['class'=>'control-label']) !!}
{!!Form::select('filterselectbox', $filters, null, ['class'=>'form-control ']) !!}
</div>
</div>
{!! Form::close() !!}
<div id="item-container">
#include('_itemlist')
</div>
<script>
$('#filterselectbox').change(function() {
var id = $('#filterselectbox').val();
var ajaxurl = '{{route('myitems', ':id')}}';
ajaxurl = ajaxurl.replace(':id', id);
$.ajax({
url: ajaxurl,
type: "GET",
success: function(data){
$data = $(data); // the HTML content that controller has produced
$('#item-container').hide().html($data).fadeIn();
}
});
});
</script>
</div>
partial view _itemlist.blade.php
<ul>
#foreach ($items as $item)
<li>{{ $item->name }}</li>
#endforeach
</ul>

Related

Laravel Ajax Update 1 Column of record

I have a user schedule record that I can update easily without one form field called disabled_dates. disabled_dates is setup to store an array of dates a user can add one at a time. What I did was add a form field with its own button using a javascript function disable() in the onclick attribute to update the record.
<div class='input-group text-center'>
{!! Form::text('disabled_dates', null , ['class' => 'form-control text-center datetimepicker15', 'id' => 'disable_date', 'placeholder' => '']) !!}
<span class="input-group-btn">
<button type="button" onclick="disable();" class="btn btn-fab btn-round btn-success">
<i class="material-icons">add</i>
</button>
</span>
Then created the disable(); like so
function disable() {
var CSRF_TOKEN = '{{ csrf_token() }}';
var disabled_date = document.getElementById('disable_date').value;
$.ajax({
type:'PUT',
url:'/schedule',
data:{_token: CSRF_TOKEN, blocked_date: disabled_date},
success:function(response) {
console.log(response);
}
});
}
The controller function used is
public function add_blocked_day(Request $request)
{
$schedule = User::find(auth()->user()->id)->schedule;
$current_blocked_dates = $schedule->disabled_dates;
$schedule->disabled_dates = $current_blocked_dates. ','.$request->blocked_date;
$schedule->save();
exit;
}
All Im getting now is too many redirects. The solution Im thinking is to seperate disabled_dates and enclose in its own form tags, because its calling the original form route somehow
I got it to work by changing the function to this
$(document).on("click", ".add-day" , function() {
var CSRF_TOKEN = '{{ csrf_token() }}';
var disabled_date = document.getElementById('disable_date').value;
$.ajax({
type:'POST',
url:'schedule/blocked-day',
data:{_token: CSRF_TOKEN, blocked_date: disabled_date},
success:function(response) {
console.log(response);
}
});
});

Laravel problems with redirect

So I am working on a laravel project and I want that if a user types in their order code, the order will show up with the details. For some reason, the order code doesn't get through the if statement, because I get the output 'Order not found.' all the time, even if I type in an order code that is present in my orders table.
TrackController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Order;
class TrackController extends Controller
{
public function index()
{
return view ('track.index');
}
public function show($id)
{
$order = Order::where('code', $id)->first();
return view('track.show',[
'order' => $order
]);
}
public function redirect(Request $request)
{
$orderCode = $request->input('order-track-id');
$order = Order::where('code', $orderCode)->first();
if(!$order){
return redirect('/track')->with('error', 'Order not found.');
}else{
return redirect('/track/' . $order->code);
}
}
}
web.php
Route::get('/track', 'TrackController#index');
Route::post('/track/redirect', 'TrackController#redirect');
Route::get('/track/{id}', 'TrackController#show');
track.index
#extends('layouts/app')
#section('content')
<div class="container">
<div class="row justify-content center">
{!! Form::open(['action' => 'TrackController#redirect', 'method' => 'post']) !!}
{!! csrf_field() !!}
<input type="number" name="input-order-track-id" id="order-track-id">
{{ Form::button('Track', ['type' => 'submit', 'class' => 'btn btn-primary'] ) }}
{!! Form::close() !!}
</div>
</div>
#endsection
What am I doing wrong and why isn't my function putting me through to the show function in the TrackController?
In your redirect controller function.
public function redirect(Request $request)
{
$orderCode = $request->input('input-order-track-id');
$orders = Order::where('code', $orderCode)->get();
if($orders->isEmpty()){
return redirect('/track')->with('error', 'Order not found.');
}else{
$order = Order::where('code', $orderCode)->first();
return redirect('/track/' . $order->code);
}
}

How do I get my variable to show in my store function

This is probably a very simple thing, but for some reason I just can't figure it out. I created a function that gets the images from my vue component.
What I'm trying to do is take the images from my postImage() and have them in my store() function, so that I can save everything into the database.
The problem I'm getting is when I do that I get this error
Too few arguments to function App\Http\Controllers\Admin\CategoryController::store(), 1 passed and exactly 2 expected
I do understand that the error is telling me that only the $request was sent and not the $image. I'm not sure how to get it working. If I've left anything out please let me know
Here is my controller
public function store(Request $request, $image)
{
$category = new Category();
$input = $this->safeInput($request);
$category->fill($input);
dd($image);
$slug = $category->slug($category->title);
$category->slug = $slug;
if($request->has('active'))
{
$category->active = 1;
}else{
$category->active = 0;
}
$category_order = $category->order_number();
$category->order = $category_order;
$category->save();
}
public function postImage(Request $request)
{
if($request->hasFile('image'))
{
$names = [];
foreach($request->file('image') as $image)
{
$destinationPath = 'product_images/category/';
$filename = $image->getClientOriginalName();
$image->move($destinationPath, $filename);
array_push($names, $filename);
}
$image = json_encode($names);
return $image;
}
}
This is my vue component
<template>
<div class="container">
<div class="uploader"
#dragenter="OnDragEnter"
#dragleave="OnDragLeave"
#dragover.prevent
#drop="onDrop"
>
<div v-show="!images.length" :value="testing()">
<i class="fas fa-cloud-upload-alt"></i>
<div>OR</div>
<div class="file-input">
<label for="file">Select a file</label>
<input type="file" id="file" #change="onInputChange" multiple>
</div>
</div>
<div class="images-preview" v-show="images.length">
<div class="img-wrapper" v-for="(image, index) in images">
<img :src="image" :alt="`Image Uplaoder ${index}`">
<div class="details">
<span class="name" v-text="files[index].name"></span>
<span class="size" v-text="getFileSize(files[index].size)"></span>
</div>
<div class="btn btn-danger" #click="funDeleteFile(index)">
Remove
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data() {
return {
isDragging: false,
//Sets the dragCount to 0
dragCount: 0,
//Makes files an array, so that we can send the files to the server
files: [],
//Makes images an array, so that we can let the user see the images
images: [],
}
},
methods: {
testing() {
console.log('This is submit images - '+this.files);
var formData = new FormData();
this.files.forEach(file => {
formData.append('image[]', file, file.name);
});
axios.post('/admin/category/post-image', formData);
},
OnDragEnter(e) {
//Prevents the default action of the browser
e.preventDefault();
// This lets the dragCount become 1, so that the image uploader changes colour
this.dragCount++;
// Changes the isDragging variable to true instead of false
this.isDragging = true;
return false;
},
OnDragLeave(e) {
//Prevents the default action of the browser
e.preventDefault();
// This lets the dragcount become 0, so that the image uploader changes to it's original colour
this.dragCount--;
// This is if the dragCount is <= 0 then the isDragging variable is false
if (this.dragCount <= 0)
this.isDragging = false;
},
onInputChange(e) {
// Grabs the files from the event
const files = e.target.files;
// Creates an array for files, so that we can loop thru it
// Send the file to the addImage method via "this.addImage(file)"
Array.from(files).forEach(file => this.addImage(file));
},
onDrop(e) {
//Prevents the default action of the browser
e.preventDefault();
//Stops the propagation into the other elements inside the one we drop and file into
e.stopPropagation();
// This is to disable the dragging of the images
this.isDragging = false;
// Grabs the files from the event
const files = e.dataTransfer.files;
// Creates an array for files, so that we can loop thru it
// Send the file to the addImage method via "this.addImage(file)"
Array.from(files).forEach(file => this.addImage(file));
},
addImage(file) {
//Checks if the file type is an image
if (!file.type.match('image.*')) {
this.$toastr.e(`${file.name} is not an image`);
return;
}
this.files.push(file);
const img = new Image(),
reader = new FileReader();
reader.onload = (e) => this.images.push(e.target.result);
reader.readAsDataURL(file);
},
}
}
</script>
my create.blade.php
#extends('layouts.admin')
#section('content')
#component('admin.components.products.category-form', [
'formUrl' => route('category.store'),
'formMethod' => 'POST',
'model' => $category,
'category_id' => $category_id,
'image' => '',
'image2' => ''
])
#endcomponent
#endsection
and my form
{{ Form::model($model, array('url' => $formUrl, 'method' => $formMethod, 'class' => 'add-form', 'files' => true)) }}
<div class="form-group">
{{ Form::label('category_id', 'Parent Category') }}
{{ Form::select('category_id', $category_id->prepend('Please Select', '0'), null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('title', 'Title') }}
{{ Form::text('title', null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
<label>Active:</label>
{{ Form::checkbox('active', 0) }}
</div>
<div id="app" class="mb-20">
<category-image></category-image>
</div>
<div class="form-group">
{{ Form::submit('Save', array('class' => "btn btn-dark btn-lg btn-block")) }}
</div>
{{ Form::close() }}
My routes
Route::resource('admin/category', 'Admin\CategoryController');
Route::post('admin/category/post-image', 'Admin\CategoryController#postImage')->name('admin.category.post-image');
UPDATE
I've tried this to pass the image to a hidden field in my form so that I can grab it in the $request in my store function.
In my CategoryController#create
$category = new Category();
$category_list = Category::with('parentCategory')->get();
$category_id = Category::pluck('title', 'id');
// I've added this.
$image = '';
return view('admin.products.category.create', compact('category', 'category_list', 'category_id', 'image'));
in my CategoryController#postImage
//I've added this to, so that I can pass the image variable to the create.blade.php
return redirect()->route('category.create', compact('image'));
then in my create.blade.php I added
'my_image' => $my_image
and in my category-form.blade.php component I added
<div id="app" class="mb-20">
<category-image></category-image>
<input type="hidden" name="image" id="image" value="{{ $my_image }}">
</div>
at the moment I haven't been able to do that either. Though I'm not sure if this is the right way to go, I'm a bit worried that some random person can then add whatever they want by using the hidden input
For what do you have the parameter $image? This is not specified in your axios.post.
public function store(Request $request)
{
$category = new Category();
$input = $this->safeInput($request);
$category->fill($input);
dd($this->postImage($request));
$slug = $category->slug($category->title);
$category->slug = $slug;
if($request->has('active'))
{
$category->active = 1;
}else{
$category->active = 0;
}
$category_order = $category->order_number();
$category->order = $category_order;
$category->save();
}
public function postImage($request)
{
if($request->hasFile('image'))
{
$names = [];
foreach($request->file('image') as $image)
{
$destinationPath = 'product_images/category/';
$filename = $image->getClientOriginalName();
$image->move($destinationPath, $filename);
array_push($names, $filename);
}
$image = json_encode($names);
return $image;
}
}
If the $request is available there, Then there is no need to pass extra $image variable.
have you tried
dd($request)
or
print_r($request->toArray()); exit;
for see what's in your request!
In your create.blade you use 'formUrl' => route('category.store'), this route calls the "store" method, right? If so, it also needs to pass the $image parameter. It would be easier to identify the problem if we could se your web routes file too.
If route('category.store') does call the store method you have a few options.
1 - If you don't really need the $image parameter for the store method, you could just remove it.
2 - If you need it in a few cases, just make the parameter optional and check if it's received before handling it. Example: store(Request $request, $image = null)
3 - If this parameter actually is required, you will have to pass it everytime, even when calling routes. Example: route('category.store', ['image' => $something]). Looking at your code at this moment in create.blade you don't have the content to pass though, so I don't think this is an option.
The problem isn't the image missing in the request object sent through the form, it is the second parameter required by the category.store method.
Even if you now send the image in the form with a hidden field, you would still need to pass it as a parameter everytime you call the category.store.
Your store method is defined like
store(Request $request, $image)
So, when you call this method, even if you're just getting the route URL with route('category.store'), you do need to send the image parameter in this call.
Example:
route('category.store', ['image' => 'image id here']);
The same goes for the route definition in your web routes file. You're using a resource route, but laravel don't expect a second parameter for the store method in a default resource, so you will need to change that.
/*
adds exception to the resource so it will not handle the store method
*/
Route::resource('admin/category', 'Admin\CategoryController')->except(['store']);
//adds a custom route that supports the $image parameter.
Route::post('admin/category/{image}', 'Admin\CategoryController#store')
Now, if you're planning to send the image through the request object, you don't need it as a second parameter, so the only thing you will need to change is to make your category.store method like that.
public function store(Request $request)

Laravel error "Missing required parameters for Route" when I use a form with a foreach loop

Missing required parameters for [Route: templates.answers.store] [URI: templates/{template}/answers]. (View: D:\Applications\xampp\htdocs\clientpad\resources\views\templates\answers.blade.php)
I am having the above error when I try and use a form with my foreach loop. I am not even sure why this is happening, maybe because I am new at Laravel. But this error goes away once I get rid of the AnswerController#store from the Eloquent form. It is possible I am doing this whole form wrong.
Here is what I want to do: A user made a template with questions, on the click of use button which goes to this url: http://clientpad.test/templates/{id}/answers they see their made questions which are shown with a foreach loop. Around it a Form is made so a user can answer the questions made. The form and answer field shows when I delete the action AnswerController#store, otherwise I get the above error.
Here is the code:
AnswerController:
public function index(Template $template, Question $question)
{
$questions = $template->questions->mapWithKeys(function($question){
return [$question->id => $question->question];
});
return view('templates.answers')->with('template', $template)->with('questions',$questions);
}
public function store(Request $request, Question $question, Answer $answer)
{
$answers = new Answer;
$answers->answer = $request->input('answer');
$answers->question_id = $request->input('question_id'); //current template id
$question->answers()->save($answers);
dd($question);
return redirect('/dashboard')->with('success', 'Your Question Was Successfully Created');
}
answers.blade.php
{!! Form::open(['action' => 'AnswersController#store', 'method' => 'POST']) !!}
#foreach ($questions as $question) <!-- Index counts the questions shown -->
<div class="panel panel-default">
<div class="panel-body">
<p class="pull-left question2"> {{$question}}</p>
<div class="form-group answer">
{{Form::label('', '')}}
{{Form::text('answer', '', ['class' => 'form-control', 'placeholder' => 'Type in your answer'])}}
</div>
</div>
</div>
#endforeach
<hr>
{{Form::submit('Save', ['class'=>'btn btn-primary'])}}
{!! Form::close() !!}
And I am just using the resource in routes.
Your are calling a route templates/{id}/answers in your Blade view that is missing the {id} parameter. Reading the error thoroughly will help you understand.
Instead of writing:
Form::open(['action' => 'AnswersController#store', 'method' => 'POST'])
You write:
Form::open(['action' => ['AnswersController#store', $template_id], 'method' => 'POST'])
The $template_id will fill the {id} in your route URL templates/{id}/answers.

laravel 5 and Ajax get data from database:

I have simple form:
{{ Form::open(array('id' => 'frm')) }}
<div class="form-group">
{!! Form::label('id','id:'); !!}
{!! Form::text('id',null,['class' => 'form-control']); !!}
</div>
<div class="form-group">
{!! Form::submit('Update',['class' => 'btn btn-primary form-control']); !!}
{!! Form::close() !!}
I want to post the values from the form input fields to the controller then in the controller mthod run a query on the database for the id value from the form. Finally, using ajax, show the results of the DB query and if there are no results show a message alerting the user.
I have tried this:
<script>
$("document").ready(function(){
$("#frm").submit(function(e){
e.preventDefault();
var customer = $("input[name=postal]").val();
$.ajax({
type: "POST",
url : "http://laravel.test/ajax",
data : dataString,
dataType : "json",
success : function(data){
}
}, "json");
});
});//end of document ready function
</script>
I have tried a couple of ways to get the post data in the controller but have had no success.
---Problem 1:
There is problem when I try to use this in route:
Route::post('ajax', function() { // callback instead of controller method
$user = App\User::find(\Input::get('id');
return $user; // Eloquent will automatically cast the data to json
});
I get sintax error,on second line for (;)
Also, I try to get data in controller and than print them:
if(Request::ajax()) {
$data = Input::all();
print_r($data);die;
}
ROUTES.PHP
Route::post('/',
['as' => 'first_form', 'uses' => 'TestController#find']);
Route::get('/', 'TestController#index');
Route::post('ajax', function() { // callback instead of controller method
$user = App\User::find(\Input::get('id');
return $user; // Eloquent will automatically cast the data to json
});
Function:
public function ajax()
{
//
// Getting all post data
if(Request::ajax()) {
$data = Input::all();
print_r($data);die;
}
}
I found a couple more ways to send data from view to controller,but even woant show posted data. I check with fire-bug,there is posted value in post request
It appears you're passing your ajax method a variable that doesn't exist. Try passing it the form data directly and see if that yields any results, you can do this with the serialize method:
$("#frm").submit(function(e){
e.preventDefault();
var form = $(this);
$.ajax({
type: "POST",
url : "http://laravel.test/ajax",
data : form.serialize(),
dataType : "json",
success : function(data){
if(data.length > 0) {
console.log(data);
} else {
console.log('Nothing in the DB');
}
}
}, "json");
});
The ajax call has console.log in it now so it will output anything returned to it in the console.
routes.php (an example)
Route::post('ajax', function() { // callback instead of controller method
$user = App\User::find(\Input::get('id'));
return $user; // Eloquent will automatically cast the data to json
});
Please bear in mind I am just putting the code as an example as you didn't put your controller code in the question.
EDIT
I'm going to make a really simple example that works for you. I have made a fresh install of laravel and coded this and it's working fine for me. Please follow along carefully.
app/Http/routes.php
<?php
// route for our form
Route::get('/', function() {
return view('form');
});
// route for our ajax post request
Route::post('ajax', function() {
// grab the id
$id = \Input::get('id');
// return it back to the user in json response
return response()->json([
'id' => 'The id is: ' . $id
]);
});
resources/views/form.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Ajax Example</title>
</head>
<body>
{!! Form::open(['url' => 'ajax', 'id' => 'myform']) !!}
<div class="form-group">
{!! Form::label('id','id:') !!}
{!! Form::text('id', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::submit('Update',['class' => 'btn btn-primary form-control']); !!}
</div>
{!! Form::close() !!}
<div id="response"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$("document").ready(function(){
// variable with references to form and a div where we'll display the response
$form = $('#myform');
$response = $('#response');
$form.submit(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url : $form.attr('action'), // get the form action
data : $form.serialize(), // get the form data serialized
dataType : "json",
success : function(data){
$response.html(data['id']); // on success spit out the data into response div
}
}).fail(function(data){
// on an error show us a warning and write errors to console
var errors = data.responseJSON;
alert('an error occured, check the console (f12)');
console.log(errors);
});
});
});
</script>
</body>
</html>

Resources