Symfony form rendered in twig template as controller is not submitting - php

I'd like to have simple "Search" input field in base.html.twig. Normally I would need to write code to maintain form in every route. To solve this problem I decided to create separate controller with route to render it directly in base.html.twig template:
<div class="top-middle col-12 col-md-6 d-flex order-2 order-md-1">
{{ render(controller("App\\Controller\\SearchController::searchProduct"))}}
</div>
It works find except nothing happens when the form is submitted. I tried it in normal way in one of my routes and it was working fine. So don't know where the problem is.
My SearchController with route which is rendered in twig :
class SearchController extends AbstractController
{
#[Route('search-product', name: 'search_product')]
public function searchProduct(Request $request)
{
$searchForm = $this->createForm(SearchProductType::class);
$searchForm->handleRequest($request);
if ($searchForm->isSubmitted() && $searchForm->isValid()) {
dump('Form submitted');
}
return $this->render('components/search-input.html.twig', [
'searchForm' => $searchForm->createView()
]);
}
}
Search input.html.twig component:
<div class="top-search">
<i class="bi-search top-search__icon"></i>
{{ form(searchForm) }}
</div>
and the main controller which renders index.html.twig with base.html.twig:
#[Route('/', name: 'home')]
public function index(FileHandler $fileHandler, SessionInterface $session, Request $request): Response
{
$products = $this->doctrine->getRepository(Product::class)->getProducts('Dresses', 4);
$products = $this->addPathToImages($products, 'Dresses');
return $this->render('shop/index.html.twig', [
'products' => $products
]);
}
The line
dump('Form submitted');
is not executed when the form is submitted. Page refreshes but nothing happens.
I think the whole logic should stay in this route/controller or I am missing something?

As requested I publish my solution:
Instead of embedding controller directly in Twig file and decided to handle my little form (just Search input, submitted by pressing "enter") with js. The reason for this is that it's impossible to redirect from embedded controller.
Code in twig:
<form id="top-search-form">
<div class="top-search">
<input id="search-string"
class="top-search__input" type="search"
placeholder="Search shop">
</div>
</form>
and code written in Javascript (requires FOSJSRouting Bundle):
const routes = require('/public/js/fos_js_routes.json');
import Routing from '/vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js';
Routing.setRoutingData(routes);
document.addEventListener('DOMContentLoaded', function() {
const searchForm = document.getElementById('top-search-form');
searchForm.addEventListener('submit', function(e) {
e.preventDefault();
const searchString = document.getElementById('search-string').value;
var url = Routing.generate('items_filter', {
'searchText': searchString
});
location.href = url;
});
})

Related

search filter is not fetching data until clicking on search button

It's a laravel vuejs project. Here is the photo of my product page :
Products were supposed to display at that page, but it's completely null until I am clicking on the search button . After clicking on the search button, the page loads the products and the search option working as well.
My codes are :
web.php ->
Route::get('/', 'App\Http\Controllers\Mastercontroller#index');
Route::get('/search', 'App\Http\Controllers\Mastercontroller#search');
Route::any('{slug}', 'App\Http\Controllers\Mastercontroller#index');
Mastercontroller.php ->
<?php
namespace App\Http\Controllers;
use App\Models\myproductcase;
use Illuminate\Http\Request;
class Mastercontroller extends Controller
{
public function index(){
return view('welcome');
}
public function search(Request $r){
$search = $r->get('q');
return myproductcase::where('name','LIKE','%'.$search.'%')->get();
}
}
productpage ->
<template>
<div>
<div class="search"><input v-model="search" type=text></input><button
#click.prevent="makesearch()">Search</button></div>
<div class="product-list">
<div v-if="showsearch==true">
<div v-for="getresult in getdata" v-bind:key="getresult.id">
<div class="product">
<h1>{{getresult.name}}</h1>
<h3>{{getresult.price}}</h3>
<p>{{getresult.description}}</p>
</div>
</div>
<div v-if="showsearch==false">
no data found
</div>
</div>
</div>
</div>
</template>
<script>
export default{
data(){
return{
search : '',
showsearch : false,
getdata : []
}
},
methods : {
async makesearch(){
fetch('/search?q='+this.search).then(hi=>hi.json()).then(hi=>{
console.log();
this.getdata = hi;
this.search = '';
this.showsearch = true;
}).catch(err=>{
console.log(err);
});
}
},
}
</script>
The problem is when you load the page for the first time, there is not get query parameter in your url, so in the line
$search = $r->get('q'); // Is equal to NULL
The query that you are doing the first time is:
return myproductcase::where('name','LIKE','%NULL%')->get();
You could use the syntax below for setting up a default parameter
$search = $r->get('q', 'default value' );
PD: Be careful with SQL Injection Read this
Edit:
Also in your Component call in your mounted method the makesearch method.
data(){
...
}
...
mounted(){
this.makesearch()
}

clean url generate GET method laravel

When i submit a GET method form url generate like :
example.com/machine?brand=xx&model=2016&color=red&km=110
But i want to generate url like :
example.com/machine/xx/2016/red/km=110
My Route :
Route::get('/machine/{brand}/{model}/{color}/{km}',['as'=>'machine.search','uses'=>'searchController#searchmachine']);
Form :
{!! Form::open(['route'=>'machine.search','method'=>'GET','class'=>'form-horizontal','role'=>'form']) !!}
You will have to do it in JS. Here is the form
<form action="machine">
<input name="brand"/>
<input name="model"/>
<input name="color"/>
<input name="km"/>
<button type="submit" onclick="window.location.href=this.form.action + this.form.brand.value + this.form.model.value + this.form.color.value + this.form.km.value;">
Submit
</button>
</form>
The submit button will generate the url
http://website.com/machine/brandvalue/modelvalue/colorvalue/kmvalue
In your case, you readapt your form by replacing route by url because using route would require you to pass parameters
{!! Form::open(['url'=>'machine','method'=>'GET','class'=>'form-horizontal','role'=>'form']) !!}
You are not using a good practice for doing your search, at first your route must look like this:
Route::get('/machine/search',['as'=>'machine.search','uses'=>'searchController#searchmachine']);
Then in your searchController:
class searchController extends Controller {
public function searchmachine(Request $request)
{
$brand = $request->brand;
$model = $request->model;
$km = $request->km;
$color = $request->color;
//Do your things.
}
}
And this should work:
example.com/machine/search?brand=xx&model=2016&color=red&km=110

Laravel Routing and Controller for Search

I'm building my first basic laravel web app, after following a few tutorials this is the first one I'm tinkering with on my own. I'm running into to some trouble with routing to a controller and then getting the correct url.
Ideally at this point I should only have two routes / and /{user}. On the homepage you can search via a form for the user and the form should take you to /{user}.
Routes (I have three cause I'm still trying to get this to work, and I think I need a POST):
Route::get('/', 'HomeController#index');
Route::get('/{user}', 'HomeController#student');
Route::post('/', 'HomeController#studentLookUp');
Home Controller:
public function index()
{
return View::make('helpdesk');
}
public function student($user) {
return View::make('selfservice')
->with('user', $user);
}
public function studentLookUp() {
$user = Input::get('ID');
return View::make('selfservice')
->with('user', $user);
}
Form:
{{ Form::open(array('class'=>'navbar-form navbar-left', 'role'=>'search'), array('action' => 'HomeController#student')) }}
<div class="form-group">
{{ Form::text('ID', '', array('placeholder'=>'ID', 'class'=>'form-control') ); }}
</div>
{{ Form::button('Search', array('class'=>'btn btn-default')) }}
{{ Form::close() }}
At this point I can search from the homepage ('/') and it will take me back to the homepage but with the searched for user which is how I want it to work except it doesn't have the right url of homepage.com/username.
Any help would be much appreciated!
First register a route to listen your search request:
1. Search Route:
Register search route.
//route search
Route::get('/search',['uses' => 'SearchController#getSearch','as' => 'search']);
2. Search View:-
Now create a search form in a view:-
<form action="/search" method="get">
<input type="text" name="q" placeholder="Search.."/>
<button type="submit">Search</button>
</form>
3. SearchController :
Now create SearchController to handle your searching logic.
SearchController :
<?php
class SearchController extends \BaseController {
public function getSearch()
{
//get keywords input for search
$keyword= Input::get('q');
//search that student in Database
$students= Student::find($keyword);
//return display search result to user by using a view
return View::make('selfservice')->with('student', $students);
}
}
Now you have to create one view selfservice to display your search result.
4. Selfservice View:
#foreach ($students as $key=> $student)
<div>
{{$student->name}}
</div>
#endforeach
Here for each student result, one link will be created. That link will be link:-
website.domain/{student}
5. Update Routes for Student
Route::get('/{student}',['uses' => 'HomeController#student','as' => 'student.show']);
UPDATE updated the answer to get student page directly
To redirect from search to website.domain\{user} follow these steps:-
1. Modify SearchController
<?php
class SearchController extends \BaseController {
public function getSearch()
{
//get keywords input for search
$keyword= Input::get('q');
//search that student in Database
$student= Student::find($keyword);
//redirect directly to student.show route with student detail
return Redirect::route('student.show', array('student' => $student));
}
}
2. Now add a function for Route student.show in HomeController
Route::get('/{student}',['uses' => 'HomeController#student','as' => 'student.show']);
In HomeController
public function student($student)
{
//here display student detail
}

How To Pass GET Parameters To Laravel From With GET Method ?

i'm stuck at this very basic form, that i could not accomplish, which i want to build a search form with an text input, and two select controls, with a route that accept 3 parameters, the problem that when the i submit the form, it map the parameters with the question mark, not the Laravel way,
Markup
{{ Form::open(['route' => 'search', 'method' => 'GET'])}}
<input type="text" name="term"/>
<select name="category" id="">
<option value="auto">Auto</option>
<option value="moto">Moto</option>
</select>
{{ Form::submit('Send') }}
{{ Form::close() }}
Route
Route::get('/search/{category}/{term}', ['as' => 'search', 'uses' => 'SearchController#search']);
When i submit the form it redirect me to
search/%7Bcategory%7D/%7Bterm%7D?term=asdasd&category=auto
How can i pass these paramters to my route with the Laravel way, and without Javascript ! :D
The simplest way is just to accept the incoming request, and pull out the variables you want in the Controller:
Route::get('search', ['as' => 'search', 'uses' => 'SearchController#search']);
and then in SearchController#search:
class SearchController extends BaseController {
public function search()
{
$category = Input::get('category', 'default category');
$term = Input::get('term', false);
// do things with them...
}
}
Usefully, you can set defaults in Input::get() in case nothing is passed to your Controller's action.
As joe_archer says, it's not necessary to put these terms into the URL, and it might be better as a POST (in which case you should update your call to Form::open() and also your search route in routes.php - Input::get() remains the same)
I was struggling with this too and finally got it to work.
routes.php
Route::get('people', 'PeopleController#index');
Route::get('people/{lastName}', 'PeopleController#show');
Route::get('people/{lastName}/{firstName}', 'PeopleController#show');
Route::post('people', 'PeopleController#processForm');
PeopleController.php
namespace App\Http\Controllers ;
use DB ;
use Illuminate\Http\Request ;
use App\Http\Requests ;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Redirect;
public function processForm() {
$lastName = Input::get('lastName') ;
$firstName = Input::get('firstName') ;
return Redirect::to('people/'.$lastName.'/'.$firstName) ;
}
public function show($lastName,$firstName) {
$qry = 'SELECT * FROM tableFoo WHERE LastName LIKE "'.$lastName.'" AND GivenNames LIKE "'.$firstName.'%" ' ;
$ppl = DB::select($qry);
return view('people.show', ['ppl' => $ppl] ) ;
}
people/show.blade.php
<form method="post" action="/people">
<input type="text" name="firstName" placeholder="First name">
<input type="text" name="lastName" placeholder="Last name">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" value="Search">
</form>
Notes:
I needed to pass two input fields into the URI.
I'm not using Eloquent yet, if you are, adjust the database logic accordingly.
And I'm not done securing the user entered data, so chill.
Pay attention to the "_token" hidden form field and all the "use" includes, they are needed.
PS: Here's another syntax that seems to work, and does not need the
use Illuminate\Support\Facades\Input;
.
public function processForm(Request $request) {
$lastName = addslashes($request->lastName) ;
$firstName = addslashes($request->firstName) ;
//add more logic to validate and secure user entered data before turning it loose in a query
return Redirect::to('people/'.$lastName.'/'.$firstName) ;
}
I had same problem. I need show url for a search engine
I use two routes like this
Route::get('buscar/{nom}', 'FrontController#buscarPrd');
Route::post('buscar', function(){
$bsqd = Input::get('nom');
return Redirect::action('FrontController#buscarPrd', array('nom'=>$bsqd));
});
First one used to show url like we want
Second one used by form and redirect to first one
So you're trying to get the search term and category into the URL?
I would advise against this as you'll have to deal with multi-word search terms etc, and could end up with all manner of unpleasantness with disallowed characters.
I would suggest POSTing the data, sanitising it and then returning a results page.
Laravel routing is not designed to accept GET requests from forms, it is designed to use URL segments as get parameters, and built around that idea.
An alternative to msturdy's solution is using the request helper method available to you.
This works in exactly the same way, without the need to import the Input namespace use Illuminate\Support\Facades\Input at the top of your controller.
For example:
class SearchController extends BaseController {
public function search()
{
$category = request('category', 'default');
$term = request('term'); // no default defined
...
}
}
Router
Route::get('search/{id}', ['as' => 'search', 'uses' => 'SearchController#search']);
Controller
class SearchController extends BaseController {
public function search(Request $request){
$id= $request->id ; // or any params
...
}
}
Alternatively, if you want to specify expected parameters in action signature, but pass them as arbitrary GET arguments. Use filters, for example:
Create a route without parameters:
$Route::get('/history', ['uses'=>'ExampleController#history']);
Specify action with two parameters and attach the filter:
class ExampleController extends BaseController
{
public function __construct($browser)
{
$this->beforeFilter('filterDates', array(
'only' => array('history')
));
}
public function history($fromDate, $toDate)
{
/* ... */
}
}
Filter that translates GET into action's arguments :
Route::filter('filterDates', function($route, Request $request) {
$notSpecified = '_';
$fromDate = $request->get('fromDate', $notSpecified);
$toDate = $request->get('toDate', $notSpecified);
$route->setParameter('fromDate', $fromDate);
$route->setParameter('toDate', $toDate);
});

Laravel 4, Showing field of one to one relationship data with jQuery method

I'm trying to show my CatatanObat model data in form with jQuery but, it doesn't appear at all
this is my url:
var url_data_catatanobat = '{{ route('data_catatanobat') }}';
this is my route:
Route::get('cat_obat/{id?}', array('as' => 'data_catatanobat', 'uses' => 'CatatanObatController#getData'));
this is function related in controller:
public function getData($no_ipd)
{
$cat_obat = PasienIri::getData($no_ipd);
return View::make('pages.catatan_obat', compact('cat_obat'));
}
this is function related in PasienIri Model:
public function getData($no_ipd)
{
return PasienIri::where('no_ipd', '=', $no_ipd)->first();
}
table 'pasieniri' and 'catatanobat' related in one to one relationship
in PasienIri Model:
public function catatanobat()
{
return $this->hasOne('CatatanObat', 'no_ipd');
}
in CatatanObat Model:
public function pasieniri()
{
return $this->belongsTo('PasienIri', 'no_ipd');
}
this is jQuery function related to this:
first:
$(document).ready(function(){
showAll();
});
});
second:
function showAll()
{
var no_ipd = $('#no_ipd').val();
dataCatatanObat(no_ipd);
}
third:
function dataCatatanObat(n)
{
link("#link-catatanobat");$("#catatanobat").load(url_data_catatanobat + '/' + n,function()
{
properti()
});
}
Field's data shown after I clicked a button in my form. text related to button in my form layout given id = no_ipd. And the button using id=search_link that from my jQuery function...
this is my button:
<div class="col-sm-1"><a class="btn btn-success icon-search icon-white form-control" id="search_link"></a></div>
and this is html code to show them in my layout
<div class="wrap">
<div class="grey demo-container">
<ul class="accordion" id="accordion-1">
<li id="link-catatanobat">Catatan Obat<ul>
<div class="konten" id="catatanobat">
</div>
</ul>
</li>
</ul>
</div>
i don't write pages.catatanobat here cause it's too long, but I hope you can imagine about how I load every field of the table in my form
for example:
<div class="col-sm-12"><input type="text" id="diagnosa" value="{{$pasieniri->catatanobat->diagnosa}}" class ='form-control' disabled></div>
{{$pasieniri->catatanobat->diagnosa}} <= that's my way to load the data
FYI, when I load "no_ipd" directly from CatatanObat Model, It works. I could show every field perfectly.
but now I want to show every field of CatatanObat by referencing from PasienIri. Cause PasienIri is the master table, where every "no_ipd" saved.
oh another information, when I try to show field's data by using normal controller without jQuery function, it appeared perfectly...
please.. help me...

Categories