I am trying to re-write an table from my view to a DataTables for easy filtering etc. For this I am using yajra/laravel-datatables. Within my original view I would conditionally return the following line:
#include("partials.delete", ["id" => $advice->id, "url" => URL::action("AdviceController#destroy")])
I would now need to return this line from my Controller which uses DataTables. But unfortuanlly, I can't seem to get it right. I also haven't found other people with this issue. My code in the controller is defined like:
return Datatables::of($advice)
->addColumn('delete', function($row){
if($row->original_user_id == \Auth::id()){
return '{{ #include("partials.delete", ["id" => '.$advice->id.', "url" => URL::action("AdviceController#destroy")]) }}';
}
})
->make(true);
But this literally returns the line of code in my view. Could someone help me to return the #include line?
Try using view()->render();
if($row->original_user_id == \Auth::id()){
return view("partials.delete", ["id" => '.$advice->id.', "url" => URL::action("AdviceController#destroy")])->render();
}
Related
I am using dompdf in my Laravel v8.26.1 app. I am also using Laravel Livewire v1.3.5.
I can get a view to download a pdf outside of Livewire, but can't seem to get it to work inside a Livewire view. I've tried every configuration I could think of, but keep running into road blocks. I am either getting an Undefined variable: workorder error, or no error at all, but also no download.
route
...
Route::livewire('/workorder/{workorder}/print', 'admin.workorders.printer')->name('admin.workorder.print')->layout('layouts.admin');
...
livewire/admin/workorders/print.blade
...
<div>
<button wire:click="generatePDF({{$workorder->id}})">Create PDF</button>
</div>
...
livewire/admin/workorders/printer.php
...
use Barryvdh\DomPDF\Facade as PDF;
...
public function generatePDF($id)
{
$record = Workorder::find($id);
$data = [
'project_id' => $record->project_id,
'project_name' => $record->project_name,
'customer_id' => $record->customer_id,
'generator_id' => $record->generator_id,
'workorder_po_number' => $record->workorder_po_number,
'workorder_number' => $record->workorder_number,
'prevailing_wage' => $record->prevailing_wage,
];
$pdf = PDF::loadView('livewire.admin.workorders.print', $data);
return $pdf->download('demo.pdf');
}
Here you go, just found this. fixed me right up. The only thing I had to change was in the $viewData variable, i just had to make it an array - ['viewData' => $viewData] and then i could access it in my view.
Here is the code in case that link ever goes down:
$pdfContent = PDF::loadView('view', $viewData)->output();
return response()->streamDownload(
fn () => print($pdfContent),
"filename.pdf"
);
I have a question about how I can search, for example, by name or surname in the INDEX view.
Is there any plugin or easy-to-use component that does not load the application too much?
Currently, I have a small form in index.ctp with one input field, where I enter what I want to search, and in controller have an if ($ this-> request-> is ('post')) after which to $this->Model->find adds condition WHERE. But I admit that this is not a nice way, it also reload the page.
This is the controller:
public function index()
{
if ($this->request->is('post')) {
$s = '%'.$this->request->getData('Search').'%';
$students = $this->Students->find('all')->where(['OR' => ['name LIKE' => $s, 'lastname LIKE' => $s]]);
$this->set('students', $this->paginate($students));
} else {
$students = $this->paginate($this->Students);
$this->set(compact('students'));
}
}
And this is the index.ctp:
<div class="input-group mb-3">
<?= $this->Form->button(__('<i class="fas fa-search"></i>'), ['escape' => false, 'class' => 'btn btn-primary']) ?>
<?= $this->Form->input('Search', ['type' => 'text', 'class' => 'form-control', 'label' => false]); ?>
<?= $this->Form->end() ?>
</div>
From what I can see you are either after a better solution to handle searching and/or a way of not reloading the page to display your search results.
If this isn't what you are after then please clarify your question to better outline what you would like you solution to look like.
You should be separating your searching out of your index function as that is only to display the content on that page. Adding conditions like you have will end up in you having a really long index function running your whole application based on the differences in the request, which isn't great.
Split out the searching into a separate function which will in turn create a new page for you to display your results.
public function index()
{
$students = $this->paginate($this->Students);
$this->set(compact('students'));
}
public function search()
{
$s = '%' . $this->request->getData('Search') . '%';
$students = $this->Students->find('all')->where(['OR' => ['name LIKE' => $s, 'lastname LIKE' => $s]]);
$this->set('students', $this->paginate($students));
}
This is well described in the tutorial on the CakePHP docs - CMS Tutorial - Creating the Articles Controller and can be related to your application as the index for you contains a form to pass search criteria to your application and the search function/page will then fetch the results and display them for you.
Don't forget to then alter your form to point it to the /search page. - Setting a URL for the Form
You will need to create a search.ctp file in your src/Template/ExampleController folder. Put your html code in there to display the results in a table or however you want to display the search results.
Finally you will need to add a route to your routes.php to allow the /search path in your application.
$routes->connect('/search', ['controller' => 'Example', 'action' => 'search']);
Now if you don't want the page to reload when you use your form then you have to use Ajax and JS/JQuery to make the request to your search method and display the results of the search function on the page dynamically. There are already a lot of good examples of this on stackoverflow and the web for using ajax and jquery for building tables from searches so I won't bother posting them here.
If you want a plugin/library solution then look at this tutorial on having search results displayed in a table using DataTables. - Search Using Datatables
install plugin https://github.com/FriendsOfCake/search
then in search configurations
$this->searchManager()
// Here we will alias the 'q' query param to search the `Students.name`
// field and the `Students.lastname` field, using a LIKE match, with `%`
// both before and after.
->add('q', 'Search.Like', [
'before' => true,
'after' => true,
'fieldMode' => 'OR',
'comparison' => 'LIKE',
'wildcardAny' => '*',
'wildcardOne' => '?',
'field' => ['name', 'lastname']
]);
I am working on a custom package for one of my projects and came up with an idea to create a custom blade directive for the elements that I want to loop through.
I made a sample code that does not work:
// WIRES
\Blade::directive('startWire', function($params) {
$wires = [
0 => [
'name' => 'test1',
'image' => 'http://image.jpg'
],
];
return "<?php foreach($wires as $wire): ?>";
});
\Blade::directive('endWire', function() {
return "<?php endforeach; ?> ";
});
And in the Blade file I wan to use it like:
#startWire()
#endWire
But I got the following error:
Array to string conversion
I tried to escape the string but nothin seems to be a good choice. Shall I extend the default Blade #foreach directive or how it supposed to work?
Thank you for your answers!
Gábor
I have been trying to get cakephp to suggest input from data that is from my tables like autocomplete. I've done some reading about how some other people have done this but still can't figure it out. Currently it seems that every time my controller is waiting for an ajax request and it is always false. No errors come up from the console some i'm not sure what i'm doing wrong. I tried removing the if ($this->request->is('ajax')) statement but then I get a error about it cannot emit headers.
Here is my search function in InvoicesController which I have taken code from someone else example but failed to implement it.
public function search()
{
if ($this->request->is('ajax')) {
$this->autoRender = false;
pr('b');
$name = $this->request->query['term'];
$results = $this->Invoices->find('all', [
'conditions' => [ 'OR' => [
'id LIKE' => $id . '%',
]]
]);
$resultsArr = [];
foreach ($results as $result) {
$resultsArr[] =['label' => $result['full_name'], 'value' => $result['id']];
}
echo json_encode($resultsArr);
}
}
And here is my search.ctp
<?php use Cake\Routing\Router; ?>
<?php echo $this->Form->input('id', ['type' => 'text']);?>
<script>
jQuery('#id').autocomplete({
source:'<?php echo Router::url(array('controller' => 'Invoices', 'action' => 'search')); ?>',
minLength: 1
});
</script>
This is my invoice table and the ids are what I want to be suggested from what users type in.
I may not be seeing your exact problem but let me point out a few things I see that might help this issue.
Remove this line. It is not necessary
$this->autoRender = false;
Instead you should be doing this at the end. See using the RequestHandler
$this->set('resultsArr', $resultsArr);
// This line is what handles converting your array into json
// To get this to work you must load the request handler
$this->set('_serialize', 'resultsArr');
This will return the data without a root key
[
{"label":"Label Value"},
{"label":"Another Label Value"}
]
Or you can do it like this
$this->set('_serialize', ['resultsArr']);
This will return data like
{"resultArr":[
{"label":"Label Value"},
{"label":"Another Value"}
]}
Replace your finder query with this.
$resultArr = $this->Invoices->find('all')
->where(['id LIKE' => $id . '%'])
// If you want to remap your data use map
// All queries are collections
->map(function ($invoice) {
return ['label' => $invoice->full_name, 'id' => $invoice->id];
});
It seems to me you might want to review the new cakephp 3 orm. A lot of hard work went into writing these docs so that they could be easily read and relevant. I'm not one to push docs on people but it will save you hours of frustration.
Cakephp 3 ORM documentation
A few minor things I noticed that are also problems.
You never define $id.
You define $name but never use it.
pr is a debug statement and I am not sure why you have it.
Based on your comment, here is an update on ajax detection.
// By default the ajax detection is limited to the x-request-with header
// I didn't want to have to set that for every ajax request
// So I overrode that with the accepts header.
// Any request where Accept is application/json the system will assume it is an ajax request
$this->request->addDetector('ajax', function ($request) {
$acceptHeaders = explode(',', $request->env('HTTP_ACCEPT'));
return in_array('application/json', $acceptHeaders);
});
I am using a Laravel jenssengers MongoDB and it is my first time seeing the word obfuscating. I see many open source options on github but nothing that does what i want.
How do i obfuscate my url from looking like this
http://blog.dev:8000/article/57780ee99a892008f64d5341
To looking like
http://blog.dev:8000/article/how-to-do-this-article
My routes expect an article id like so
Route::get('/article/{article_id}', [
'uses' => 'MainController#singleArticle',
'as' => 'article'
]);
...And Controller
public function singleArticle($article_id){
$article = Article::find($article_id);
return view('article',['article' => $article]);
}
And i am assuming it is quicker working with ids rather than text.(Correct me if i am wrong) Therefore changing the route to ...
Route::get('/article/{article_title}', [
'uses' => 'MainController#singleArticle',
'as' => 'article'
]);
and controller to
public function singleArticle($article_title){
$article = Article::where('title',$article_title)->first();
return view('article',['article' => $article]);
}
Would be a bad choice that i might regret later when two articles have the same title?
So how do i obfuscate my routes, to look like the title of the article which is being fetched from the database?