In symfony2 with sonata: How to pass a variable to the template defined for a given field of the listmapper in the method configureListFields? - symfony-sonata

Using Symfony2 with Sonata, in a list, fields templates can be overwritten and assigning variables to templates, i.e setTemplateVar(), can sometimes be useful! (not talking about form where 'attr' serves this purpose but list...)
I would like to know what would be the best approach to pass a variable to the template defined for a given field of the listmapper in the method configureListFields ?
<?php
namespace Acme\AcmeBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
class AcmeAdmin extends Admin
{
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('acme_field')
->add('date', 'date', array(
'template' => "AcmeBundle:CRUD:list_date.html.twig",
// 'dateFormat' => "Y-m-d",// ---> how to pass this var to twig ?
))
->add('_action', 'actions', array(
'actions' => array(
'edit' => array(),
'delete' => array(),
),
))
;
}
A solution to the specific problem of translating and formatting the date is already implemented with the twig template as follows:
{% block field%}
{% if value is empty %}
{% else %}
{# retrieving the dateFormat variable from the listmapper #}
{% if dateFormat is defined %}
{{ value|date(dateFormat)|title }}
{% else %}
{{ value|date('m / Y') }}
{% endif %}
{# passing the locale in some way here would be great, it is not available in twig.. #}
{# scratch that, it is not necessary with intl.extension... #}
{% if locale is defined %}
{% set dflt_locale = locale %}
{% else %}
{% set dflt_locale = 'fr_FR.UTF-8' %}
{% endif %}
{{ value|localizeddate('medium', 'none', dflt_locale)|title }}
{% endif %}
{% endblock %}
However, my goal is to be able to retrieve a variable there from the listmapper.
In the example proposed, the dateFormat would be a good one to pass along...
The issue about the locale is fine actually, as I realized it does not need to be passed to localizeddate... it is already available through the intl extension.
The following post answer lead me to that conclusion as I could not define locale, but by not adding the parameter it was resolved!
Localize dates in twigs using Symfony 2
hence:
{{ value|localizeddate('medium', 'none')|title }}
Cheers in advance for any response related to the dateFormat parameter!
Vinz

Try in the Twig
field_description.options.YOURFIELDNAME
defined here
->add('date', 'date', array(
'template' => "AcmeBundle:CRUD:list_date.html.twig",
'YOURFIELDNAME' => 'Blablo'
))
Cheers

In the end, the most straightforward solution was to define a var in the Admin class as follows:
<?php
namespace Acme\AcmeBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
class AcmeAdmin extends Admin
{
// two options to define var and make them available to twig by admin. mechanism
public $dateFormat = "Y-m-d";// ---> this var is available in twig : admin.dateFormat
// or to allow better relation to context
public $parameters = array();// ---> this array is available in twig : admin.parameters.x.y.z
protected function configureListFields(ListMapper $listMapper)
{
// assuming the $dateFormat is not set, by convention it could be defined here with proper intent in mind
// it could then be contained in an array like that
$this->parameters = array('listmapper' => array('dateFormat' => 'Y-m-d',),);
// then specialized in twig : admin.parameters.listmapper.dateFormat
$listMapper
->addIdentifier('acme_field')
->add('date', 'date', array(
'template' => "AcmeBundle:CRUD:list_date.html.twig",// checking admin.parameters.listmapper.dateFormat
))
->add('_action', 'actions', array(
'actions' => array(
'edit' => array(),
'delete' => array(),
),
))
;
}
Then in twig:
{% block field%}
{% if value is empty %}
{% else %}
{# retrieving the dateFormat variable from the listmapper by convention...
twig is very forgiving in eval, so checking for defined var is peachy
e.g if admin.parameters is not defined or empty then else is triggered
#}
{% if admin.parameters.listmapper.dateFormat is defined %}
{{ value|date(admin.parameters.listmapper.dateFormat)|title }}
{% else %}
{{ value|localizeddate('medium', 'none')|title }}
{% endif %}
{% endif %}
{% endblock %}
Thanks to Sonata Admin: Add custom triggers/actions to list/edit action I realized/remembered/connected the dots... that twig has access to the admin variable, so by defining a variable in the class we can retrieve it in twig.
Now, it is just a question of convention to put in place a sort of constraint to a container for the admin variables. (cf parameters array)
For this particular case, this solution does not add any point as localizeddate serves well my purpose, however, for the sake of the argument it is good to know IMHO.
Cheers,
Hope that helps!
Vinz

Related

Attempt to read property "degree" on null

i have created a profile where users can add their education fields.
when there is no value in the database it throws an error. how can i get rid of this ? Attempt to read property "degree" on null.
public function myEducations()
{
return $this->hasMany('App\Models\Education','user_id')->orderByDesc('endDate');
}
controller
public function myProfile(\App\Models\User $user)
{
$user = Auth::user();
$education = $user->myEducations->first();
return view('candidate.profile',compact('user','education'));
blade
{{ $education->degree }} - {{ $education->fieldOfStudy }}
If the users of you application are filling in their education details later only. You should ideally catch this condition when rendering your view. For example you could try the following:
#if ($education)
{{ $education->degree }} - {{ $education->fieldOfStudy }}
#else
<p>Education details not available</p>
#endif
You have to inspect in an if statement $education->degree is not null.
If not null, degree has value, this part will render.
Else, it doesn't have value so else block appears in template.
#if(null !== $education->degree)
{{ $education->degree }} - {{ $education->fieldOfStudy }}
#else
// there is no degree
#endif

How to output message after form submit on the same page?

When a user sumbit a form I need to output message for him on the same page.
When I submit a form the page refreshes, handler fires (php function), some POST data inserts into database, I set $this['success'] = 1 and then check with Twig:
{% if success %}
here is many tags with information and a message
{% else %}
here is a form
{% endif %}
But if I press F5 the form is resubmitting, the insert query executes again.
Do this request with AJAX isn't a real option.
There are numerous ways to answer this question (use Cache, database, cookies, session). This is really easy using Session Flashing or in this instance I am going to show you how to do it with Returning a redirect with flash data.
Spin up a CMS Page
Place HTML Form code: *Note the {{ something }} is important to show our response after submitting the form. This request does not use AJAX.
{{ something }}
{{ form_open({ request: 'onSubmit', class: 'row', autocomplete: 'off' }) }}
{{ form_input('text', 'something', '', { class: 'input padding' }) }}
{{ form_submit('Submit', { class: 'button padding' } ) }}
{{ form_close() }}
PHP code:
function onStart() {
$something = Session::get('something');
$this['something'] = $something;
}
function onSubmit() {
$something = Input::get('something');
return Redirect::refresh()->with('something', $something);
}
Test and enjoy one way to create a message after submitting a form.
If you are using laravel then you can easily implement to handle this functionality
In View file you need to write this code, which will display message on the same page where you are displaying form.
file.blade.php file
#if(Session::has('success'))
<div class="alert alert-success">
{{ Session::get('success') }}
</div>
#endif
FormController.php
public function addUser(Request $request){
User::create([
'name' => $request->name,
'email' => $request->email,
'gender' => $request->gender,
'contact' => $request->contact,
.....]);
//below code help to display the message that you want on same page whereuser entered data
return back()->with('success', 'Thanks you for adding!!');
}
return back()->with('success', 'Thanks you for adding!!');
use this code for laravel project to display message on same page

Laravel Blade loop through config array variable

In my config/locale.php I have an array 'displayLanguage' which contain key=>value pairs
How can I loop through this array in blade ?
I have tried the following
#foreach ( {{ Config::get('app.locale.displayLanguage') }} as $itemKey => $itemVal)
{{ $itemKey }}
#endforeach
I am getting syntax error, unexpected '<'. tried also some other veriation to loop this var without passing it through the controller
If your file is in config/locale.php then you call config('locale.displayLanguage');
#foreach(config('locale.displayLanguage') as $key => $value)
{{ $key }}
#endforeach
I am using the global helper config() in a blade file.
It also appears you have extra curly braces in your foreach loop

Eloquent: get related model with aliases

I have a view where a related model property gets displayed.
{{ $product->category->title_en }}
I'd rather put this like
{{ $product->category->title }}
And make the locale selection in my controller.
For example with the main model:
View:
{{ $product->title }}
Controller:
if ($locale === 'en') {
$product = Product::where(id of something)->get([
'title_en AS title'
])
}
How can I set aliases for the related?
Or is there a better option?
I've created a helper function for this for my own project. As the locale is the first in all urls, I explode it and use it like this.
function translate($model, $column)
{
$url = explode('/', Request::path());
return $model[$column . '_' . $url[0]];
}
In the view file, I use:
{{ translate($product, 'title') }}
Alternatively you can use App::getLocale() to get the current locale.
you can use select() but you have to write names of other columns too in select()
if ($locale === 'en') {
$product = Product::where(id of something)
->select('title_en as title','col2','col3'....)
->get()
}

How to get value of Input object in a Route Filter?

I've been following the Laravel guides in their website, but there's one thing that it's not clear to me. In the tutorial they describe this filter:
Route::filter('old', function() {
if (Input::get('age') < 200) {
return Redirect::to('home');
}
});
What is the value of Input how does it get assigned?
The Route using that filter is not very descriptive:
Route::get('user', array('before' => 'old', function() {
return 'You are over 200 years old!';
}));
My guess is that Input represents the user, but how does it get assigned? He's not fetching the user from the DB, nor anything.
The ´Input´ (pretty much) always come from a form the user posted on your page. In this case you should have an input field named 'age' on it.
Take a look at requests and inputs: Laravel 4 Requests & Input
A form example for it, written in Laravel Blade:
{{ Form::open(array('url' => 'foo/bar')) }}
{{ Form::text('name') }}
{{ Form::text('age') }}
{{ Form::submit('Submit this form') }}
{{ Form::close() }}
As soon as you submit this form you will be able to:
echo Input::get('name');
echo Input::get('age');
or just everything you submited:
var_dump(Input::all());

Resources