How to dynamically load/render Laravel Collective form? - laravel

I'm devising a small CMS for the in-house development team, where all have experience working with laravel.
The CMS requires a small feature where the services that are listed can have a quotation form attached. Instead of creating a completely separate module to add elements & other separately, I wanted to have the system in a manner that the developer adds the laravel collective form code, which we store in the database.
While retrieving, we render the form server side.
Here's my implementation
Controller
public function show($id)
{
$data['page'] = Service::where('slug', $id)->first();
if ($data['page']) {
....
$data['form'] = $data['page']->quoteform()->first();
....
And in the view
{!! $form['html'] !!}
But this is definitely won't help, so I tried this approach of rendering the collective form
$data['form'] = View::make('website.includes.render-form',['form'=>$data['page']->quoteform()->first()]);
But I'm not sure if this should work, as I couldn't make it work.
Looking forward to a solution if at all the approach I choose is possible, if yes or can be done, would like to know more on the same.
TIA
Edit 1:
I used the following blade command Blade::compileString('string here') which helped to a certain extent.
where I'm getting the following result

You can render the HTML of a view using render() method. So you can update to this :
$data['form'] = View::make('website.includes.render-form',
['form' => $data['page']->quoteform()->first()]
)->render();
Now the $data['form'] will have rendered HTML which you can use in blade using {!! $data['html'] !!} if you are passing $data to your main view.

Related

Laravel - Generate a PDF from a form , including also the user's signature

I have a big chalenge for my level.
The title is self explanatory : Generate a PDF from a form , including also the user's signature, using Laravel.
My laravel and general php level is basic. I know how to make a basic blog on laravel (like all guys who have followed laracasts or similar) but this one I find it tough cause I see there are many concepts from different places going on at the same time and I have many gaps of knowledge.
It would be at least very helpful to know which packages are the best ones to do all this. I have been trying with DOMPDF and https://github.com/szimek/signature_pad. But I have read that with DOMPDF I can't use active forms ... I have also checked MPDF.
What I would mainly need is a view , where there is a form , where there is a signature pad for the user to sign after the form , and this, after submitting generates a pdf.
Any starting points on what to read, study, focus ?
Already how to mix the image of the signature, which the script is on js, with the data of the form seems like the everest to me.
What I can't neither imagine is how to deal with the different controllers ..
Hats off for accepting that you lack the knowledge to do this on your own. It is no shame to ask and I guess it will make your life a lot easier after all as well.
My advice is to split the whole task into suitable sub-tasks that you are able to handle. In my opinion that are:
Create an absolutely normal HTML form that you can submit.
You'll need one controller with two functions for this. One function will display the form and the other one will handle the submitted data once the form gets submitted.
class MyFormController
{
public function getForm()
{
return view('my.form');
}
public function postForm(Request $request)
{
// do something with the form data in $request
}
}
I guess you know how to put together a proper HTML form.
Generate the PDF with the submitted form data.
The way most pdf generator packages of Laravel work is by using a blade template view. For you that is actually quite beneficial, because you already know how to put together an HTML view!
So if we translate this into code based on the barryvdh/laravel-dompdf package, we get something like this:
public function postForm(Request $request)
{
$pdf = PDF::loadView('my.pdf', [
'name' => $request->input('name'),
'address' => $request->input('address'),
// ... and more data if you like
]);
return $pdf->download('signed_form.pdf');
}
Of course we will also need a blade template. According to the name it will have the path and file name resources/views/my/pdf.blade.php:
<table>
<tr>
<th>Name:</th>
<td>{{ $name }}</td>
</tr>
<tr>
<th>Address:</th>
<td>{{ $address }}</td>
</tr>
</table>
Now, as we do have the form and PDF generation itself, we can go on to the signature.
To be fair, I've never done anything similar myself so far. But after a very quick search I came across the JavaScript package szimek/signature_pad, which looks incredibly promising. I think the setup is quite self explanatory, but here is what I understood so far:
Add the script tag (<script src="...">) given in the documentation to your form view.
Add a hidden input field to your form (<input type="hidden" name="sig" id="sig">).
Add a <canvas> HTML element to your form view. Give it an identifier: <canvas id="signature">.
Add another script tag but with custom JavaScript code below the one you already added. Something like this:
<script type="text/javascript">
var canvas = document.getElementById('signature');
var signaturePad = new SignaturePad(canvas);
function onFormSubmit()
{
document.getElementById('sig').value = signaturePad.toDataURL();
}
</script>
You'll now also have to add onsubmit="onFormSubmit()" to your <form ...> tag. What this script does is to first initialize the signature pad but then also to set the value of the hidden input field to the contents of the signature pad.
Last thing you'll want to do is to add the submitted sig value to the view that is used to generate the pdf. And in the view itself you'll have to use the submitted sig data in a new image element: <img src="{{ $sig }}">
And if you are lucky, all of what I just wrote straight out of my mind (without any testing anything of it) works right out of the box. If not, you should at least have an idea what the steps are to achieve your goal.
By the way, of course you can make all the views look fancy. But be aware that PDFs cannot display as much information as HTML can. So you will definitely lose information and styling at some points when you convert a view to pdf.

Laravel Multi Select with Select2 Ajax

I implemented a Many To Many relation between Posts and Tags. I am using Select2 Ajax for Multi Select and html is rendered by the Spatie/HTML package.
In the create form, I can select the tags and while i same the database table updates successfully. I can also show the tags.
I am facing an issue in the edit form. I am using the same create form for the edit and though the Tags has been attached earlier i can not see those as selected. What is the solution of this. Some of the codes are mentioned below.
Form
{{ html()->multiselect('tags_list', '', $posts->tags->pluck('id')->toArray())->class('form-control select2-tags')) }}
Model:
public function tags()
{
return $this->belongsToMany('App\Models\Tag');
}
The following code works, but is there any better solution? may be via Model?
{{ html()->multiselect('tags_list', $posts->tags->pluck('name', 'id'), $posts->tags->pluck('id')->toArray())->class('form-control select2-tags')) }}

Laravel 5 - getting data to a view

I think this is slightly different to the usual controller passing data to the view. I have a Project which has one DocumentOne. Within my app, the user creates a Project. This then redirects them to the show page for this project.
So with the project created, and the user on the show page for that project, I display the project ID. I then provide a select menu where the user can select a Document to display. So say I am in Project with the ID of 1, I then decide to show DocumentOne for this project. This displays a form with inputs for DocumentOne.
When the user fills in the form and submits, the data is saved to the database. The Project ID is the foreign key for DocumentOne. The following route is set up for DocumentOne
Route::resource('projects.documentOne', 'DocumentOneController');
Now I have data for DocumentOne which is linked to the Project with an ID of 1. However, if I now go back to the projects show page and then select Document One from the dropdown again, all I see is an empty form. This is obviously because the controller for this is
public function show(Project $project)
{
return view('projects.show', compact('project'));
}
So I am never passing it data for DocumentOne because theoretically it is not created when the Project is first shown. What I want to do is when the Document is selected in the Projects show page, is to have the form populated with whatever is in the database for that Document. If nothing is in the database, then the form will be empty. I have a DocumentOne Controller, but I dont know if I can link this to the Projects show page. I was thinking about doing something like this in the DocumentOne controller
public function show(DocumentOne $documentOne)
{
return view('projects.show', compact('documentOne'));
}
But not sure this will work. Hope I have not been too confusing and you understand what I am attempting, hoping someone can offer advice on how best to handle this situation.
Thanks
In my previous project, I also deal with such requirement, I thought so. Here my solution to solve such requirement.
Actual code calling from ajax.
Routes
get('setFlashData',function(Request $request){
$final_response = array();
$data_information = $request->except('_token');
$request->session()->flash('cmg_quick_create_data', $data_information);
if($request->session()->has('cmg_quick_create_data')){
$final_response['result']['success'] = true;
}
return response()->json($final_response);
});
But according to you requirement:
$data_information = $request->except('_token');
$request->session()->flash('cmg_quick_create_data', $data_information);
My basic functionality was, to share form data from Quick Create Section which is pop-up form to Full create form section, and whenever user click to "Go To Full Form" button from pop up, ajax call mentioned function which will set the flash data and than on destination side I only check weather its contain the flash data or not. and deal according to data.
#if (Session::has('cmg_quick_create_data')) {
{!! Form::model(Session::get('cmg_quick_create_data'),["class"=>"form-horizontal","data-parsley-validate"=>"data-parsley-validate",'role'=>'form','files'=>true]) !!}
#else
{!! Form::open(["class"=>"form-horizontal","data-parsley-validate"=>"data-parsley-validate",'role'=>'form','files'=>true]) !!}
#endif
I can understand this solution might be different from you requirement but hope full to figure out your solution. Look forward to hearing from you if still unclear from my side.

How to make a laravel 5 view composer

I'm still learning Laravel and I'm working on a small project to help me understand better. In the project, I am in need of a global array, so that I may display it or its attributes on every view rendered. sort of on a notification bar, so that each page the user visits, he/she can see the number of notifications (which have been fetched in the background and are stored in the array).
I have done some research, and realized that I have to fetch and compile the array in a view composer I think. But everywhere I go, I cant seem to understand how to make a view composer.
I need to fetch the relevant rows from the database table, and make the resulting array available to each view rendered (I'm thinking attaching it somehow to my layouts/default.blade.php file.). Please help, any and all advice is greatly appreciated:)
You can now inject services on your view
More info here: https://laracasts.com/series/whats-new-in-laravel-5-1/episodes/2
You have to use Sub-Views of laravel blade. I guess your functionality is like a sidebar or like a top bar which will be rendered at every page.
//Your Controller pass data
class YOUR_CONTROLLER extends Controller {
public function index()
{
$data = YOUR_DATA;
return view('YOUR_VIEW_FILE', get_defined_vars());
}
}
//In Your View File
#extends('LAYOUTS_FILE')
#section('YOUR_SECTION')
#include('YOUR_SUB_VIEW_FOR_NOTIFICATION')//You need not pass any data passed all data will be available to this sub view.
#endsection
In your sub view
//Do what ever you want looping logic rendering HTML etc.
//In your layout file just yield or render the section that's it
#yield('YOUR_SECTION')
More explanation can be found Including Sub-Views

Dynamic layouts in CakePHP

Sorry about the question title, but I couldn't find a more appropriate way to phrase this.
I am currently building a CakePHP powered website and I'm not quite sure how to approach the following issue. The website looks something like the follwing mockup:
.
The greyed out areas are part of the layout, because their content does not change between views. In the sidebar, I have a collection of ads who are linked to several models. I need controller logic to determine the picture associated with an ad. Also, the ad list needs to be dynamic. Where should I put the logic for building the sidebar?
I've thought about:
putting the logic into the AppController (beforeFilter / afterFilter) - the problem is I can't use the controller logic I need (the other controllers inherit from AppController, I'm not sure how to use them there).
making a component - is it okay to build components that rely on controllers?
replicating the sidebar code in all controllers that render views - this seems kind of stupid to me.
What is the Cake way for this?
Update
After some reading and experimenting, I've gotten to refactoring most of it.
I obtained the best performance by moving the logic for building my ads in the model (eliminating the component that retrieved the pictures) and not using requestAction. It's almost three times faster and the code looks much better.
I've done something similar for data-driven navigation. I put my logic in AppController::beforeRender and haven't had any problems. I'm not sure I understand your concern related to controller inheritance. I retrieve my menus via:
$menus = $this->NavMenuItem->groupByMenu();
$this->set( compact( 'menus' ) );
I then created an element that renders the menu. It's executed by the layout via:
<?php echo $this->element( 'navigation', array( 'id' => 'secondary', 'menu' => $menus['SECONDARY'] ) ) ?>
If that doesn't help, maybe you can further explain your issue with controller inheritance in a comment.
I guess the answer is requestAction in case the results are cachable:
http://book.cakephp.org/view/434/requestAction
It can be done in this way:
Create an element that will help in layout of the Ad Block
Create one or more controller that will generate the data required for rendering of the block
Use requestAction for getting the data out of the models and into the element.
Check the cake book, there is an example of an element where data from Post Model is used to display top/latest 5 posts. Your requirement, I feel, is very similar to it.
Alex,
you're getting a SQL error because the build() function has to be in the Sidebar model, not controller. Also, you don't necessarily need to use $user = array('Sidebar'); you could calling Sidebar in all of your models with this:
$Sidebar = ClassRegistry::init('Sidebar'); and then $Sidebar->find();, $Sidebar->build(); etc.
Or, if you only need to call the build() function from the Sidebar model, you could do this:
$sidebar = ClassRegistry::init('Sidebar')->build();
$this->set('sidebar', $sidebar);
Cheers.

Resources