I make an entity "comment" with fields id, pseudo, email, comment and published_at.
My entity :
/**
* #ORM\Column(type="datetime")
*/
private $published_at;
public function __construct()
{
$this->published_at= new \DateTime();
}
public function getPublishedAt(): ?\DateTimeInterface
{
return $this->published_at;
}
public function setPublishedAt(\DateTime $published_at): self
{
$this->published_at = $published_at;
return $this;
}
My migration:
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE comment (id INT AUTO_INCREMENT NOT NULL, pseudo VARCHAR(25) NOT NULL, email VARCHAR(255) NOT NULL, comment LONGTEXT NOT NULL, published_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
I make a controller :
$comments = $commentRepo->findBy([], ['published_at' => 'desc']);
// dd($comments);
return $this->render('comment/comments.html.twig', [
'commentForm' => $form->createView(),
'comments' => $comments,
]);
My render twig :
<div>
{% for comment in comments %}
<div class="text-light">
{{ comment.pseudo }}
{{ comment.published_at|date('d/m/Y H:i:s')}}
{{ comment.comment | raw }}
</div>
{% endfor %}
</div>
For {{comment.pseudo}} and {{comment.comment}} display well
But for {{comment.published_at}} I have this error :
Neither the property "published_at" nor one of the methods "published_at()", "getpublished_at()"/"ispublished_at()"/"haspublished_at()" or "__call()" exist and have public access in class "App\Entity\Comment".
Related
In a twig form template in Symfony 4 app I need to have an attribute with a variable.
Exemple:
{{ form_widget(myform.field, {'attr': {'class': 'bidding-slider','data-slider-value': '800'}}) }}
I need to put a variable in 'data-slider-value' instead of a manual value.
I tried :
{{ form_widget(myform.field, {'attr': {'class': 'bidding-slider','data-slider-value': '{{ variable }}'}}) }}
but it do not work...
{{ variable }} alone return well the value I need to put in 'data-slider-value'.
Second tried:
I have Extended form class 'TextType' method buildView.
To do that I added this file : src/Form/Extension/TextTypeExtension.php
// src/Form/Extension/TextTypeExtension.php
namespace App\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FileType;
class TextTypeExtension extends AbstractTypeExtension
{
/**
* Return the class of the type being extended.
*/
public static function getExtendedTypes(): iterable
{
// return FormType::class to modify (nearly) every field in the system
return [TextType::class];
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$tjm = $form->get('dailyrate')->getData();
$view->vars['attr']['data-slider-value'] = $tjm;
}
}
But now I am not sure of the way to use that in my form template...
Thank you very much for helping me.
Alex
Extend your form's class method buildView:
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['attr']['data-slider-value'] = ...//
}
I want to use the second datasource [data] to replace the IDs of a column with the NAMEs from another table(from another datasource) which have a common ID field. I have tried with kendo-grid-span-column, but it is working only with the same datasource as the grid.
<form novalidate #myForm="ngForm">
<kendo-grid
[data]="gridData | async"
<kendo-grid-column field="Contract_id" title="Contract_id"></kendo-grid-column>
<kendo-grid-span-column>
<kendo-grid-column field="Employee_id" title="Employee_id">
</kendo-grid-column>
<ng-template kendoGridCellTemplate let-dataItem>
<h4>{{dataItem.NameFromAnotherDataSource}}</h4>
</ng-template>
</kendo-grid-span-column>
<kendo-grid-column field="Contract_Num" title="Contract_Num"></kendo-grid-column>
</kendo-grid>
Any ideas?
Thanks,
Martin
I found the way.
container.component.html
<kendo-grid-column field="Employee_id" title="Employee" width="200">
<ng-template kendoGridCellTemplate let-dataItem>
<h4>{{category(dataItem.Employee_id)?.Name}}</h4>
</ng-template>
<ng-template kendoGridFilterCellTemplate let-filter>
<my-dropdown-filter
[filter]="filter"
[data]="employees"
textField="Name"
valueField="Employee_id">
</my-dropdown-filter>
</ng-template>
container.component.ts
private employees;
constructor(
public dataServiceEmployees: EmployeesDashboardService,
) {
this.dataServiceEmployees.fetch('Employee',this.gridState).subscribe((x) => this.employees = x.data);
}
public category (id: number): any {
if(this.employees){
return this.employees.find(x => x.Employee_id === id);
}
}
And using a filter template:
custom.filter.ts
import { Component, Input } from '#angular/core';
import { CompositeFilterDescriptor } from '#progress/kendo-data-query';
import { FilterService, BaseFilterCellComponent } from '#progress/kendo-angular-grid';
#Component({
selector: 'my-dropdown-filter',
template: `
<kendo-dropdownlist
[data]="data"
(valueChange)="onChange($event)"
[defaultItem]="defaultItem"
[value]="selectedValue"
[valuePrimitive]="true"
[textField]="textField"
[valueField]="valueField">
</kendo-dropdownlist>
`
})
export class DropDownListFilterComponent extends BaseFilterCellComponent {
public get selectedValue(): any {
const filter = this.filterByField(this.valueField);
return filter ? filter.value : null;
}
#Input() public filter: CompositeFilterDescriptor;
#Input() public data: any[];
#Input() public textField: string;
#Input() public valueField: string;
public get defaultItem(): any {
return {
[this.textField]: "Избери...",
[this.valueField]: null
};
}
constructor(filterService: FilterService) {
super(filterService);
}
public onChange(value: any): void {
this.applyFilter(
value === null ? // value of the default item
this.removeFilter(this.valueField) : // remove the filter
this.updateFilter({ // add a filter for the field with the value
field: this.valueField,
operator: "eq",
value: value
})
); // update the root filter
}
}
I would like to reuse a select menu, but change every time the id and the name for it in Twig. How could it be done?
I thought of a wrapper block about the select menu and then extend it each time of reuse. But how to set the values for id and name using {{ parent() }}?
I do this by storing and creating the keys in my custom Twig_Extension class, here is a small setup for it. By keeping it global I can ensure unique id's in every view/macro/include ...
example.twig
{% for i in 1..5 %}
<ul id="{{ get_unique_key('my_menu') }}">
<li>Foo</li>
</ul>
{% endfor %}
ProjectTwigExtension
class ProjectTwigExtension extends Twig_Extension {
private $keys = array();
public function getFunctions() {
return array(
new Twig_SimpleFunction('get_unique_key', array($this, 'getUniqueKey')),
);
}
/**
* Create an unique HTML identifier
*
* #param $name String to make unique
*
* #returns String
*/
public function getUniqueKey($name) {
if (!in_array($name, $this->keys)) {
$this->keys[] = $name;
return $name;
}
$i = 0;
while(in_array($name.++$i,$this->keys)) {}
$this->keys[] = $name.$i;
return $name.$i;
}
public function getName() {
return 'ProjectTwigExtension';
}
}
Register extension
$twig = new Twig_Environment($loader);
$twig->addExtension(new ProjectTwigExtension());
I'm trying to figure out how to check the existance of an object while doing a for loop in twig.
This is how my code looks like.
{% for topic in topics %}
{% set id = topic.id %}
{% set ratings = authRatings.id %}
{% if ratings is defined %}
{% else %}
{% endif %}
{% endfor %}
topic.id is the needle and authRatings is a haystack of different objects named after its topic_id. If an object match the topic.id ratings should be defined.
object
(stdClass)[76]
public '24' =>
object
(stdClass)[77]
public 'topic_id' => string '24' (length=2)
public 'user_id' => string '2' (length=1)
public 'likes' => string '0' (length=1)
public 'dislikes' => string '1' (length=1)
public 'time' => string '1348927295' (length=10)
public '15' =>
object
(stdClass)[78]
public 'topic_id' => string '15' (length=2)
public 'user_id' => string '2' (length=1)
public 'likes' => string '1' (length=1)
public 'dislikes' => string '0' (length=1)
public 'time' => string '1348927363' (length=10)
You could write a custom function that does the job. something like this:
$twig = new Twig_Environment($loader);
$twig->addFunction('searchRatings', new Twig_Function_Function('twig_search_ratings'));
function twig_search_ratings($topic_id, $ratings) {
/* do the search in php */
}
In a Sonata admin form, I'd like to display all images related to the current object. Don't need to edit them.
I managed to get this working with an entity field type and its property option to select the image URL as label so I can call all pictures in the template :
->add('image', 'entity', array(
'class' => 'Hop\HopBundle\Entity\Image',
'property' => 'image_url',
'query_builder' => function($er) use ($object) {
return $er->createQueryBuilder('i')
->where('i.object = :object')
->setParameter('object', $object)
;
},
'expanded' => true,
))
.
{% for child in form %}
<img src="{{ child.vars.label }}" alt="{{ child.vars.label }}" />
{% endfor %}
It's because it seems that the entity type only give label and one value to the template.
But I'd like to get also image width, descriptions, date, ... In other word : how can we get each entire related image object in the Twig template ?
Thanks.
So I googled it a lot and here's what worked for me (Symfony 2.2)
Updated as #flu suggested in a comment
{% for key, child in form %}
<div>
{% set entity = form.vars.choices[key].data %}
{{ form_widget(child) }}
{{ form_label(child) }}
</div>
{% endfor %}
and entity is the child object.
As of Symfony 2.3 there will be just form.vars.data, if I understand correctly: https://github.com/symfony/symfony/pull/5023
I´ve spend the whole day to get a solution for this problem.
First I created a new FormType which extends the ChoiceType:
class NomineesType extends AbstractType
{
protected $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$submissionRepository = $this->em->getRepository('BundleName:Submission');
$choices = $submissionRepository->findBy(array(
'nominee' => true
));
$resolver->setDefaults(array(
'choices' => $choices
));
}
public function getName()
{
return 'nominees';
}
public function getParent()
{
return 'choice';
}
}
Than I had to register the service:
services:
form.type.nominees:
class: Bundle\Form\Type\NomineesType
arguments:
entityManager: "#doctrine.orm.entity_manager"
tags:
- { name: form.type, alias: nominees }
After that I added the new type to my form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$game = $this->game;
$builder->add('submission', 'nominees', array(
'expanded' => true,
'multiple' => false
));
$builder->add('email');
}
Now I am able to get all properties in my twig-template:
{% block nominees_widget %}
{% spaceless %}
{% if expanded %}
<ul {{ block('widget_container_attributes') }}>
{% for child in form %}
<li>
{{ child.get('form').get('label').firstname }}
{{ child.get('form').get('label').lastname }}
{{ form_widget(child) }}
{{ form_label(child) }}
</li>
{% endfor %}
</ul>
{% else %}
{# just let the choice widget render the select tag #}
{{ block('choice_widget') }}
{% endif %}
{% endspaceless %}
{% endblock %}
Because the choice list is returning only integer values I´ve created a new data transformer to transform the id of the choice into an entity:
class IntToEntityTransformer implements DataTransformerInterface
{
/**
* #var ObjectManager
*/
private $om;
/**
* #param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object (issue) to a string (number).
*
* #param Issue|null $issue
* #return string
*/
public function transform($issue)
{
if (null === $issue) {
return "";
}
return $issue->getNumber();
}
/**
* Transforms a string (number) to an object (issue).
*
* #param string $number
* #return Issue|null
* #throws TransformationFailedException if object (issue) is not found.
*/
public function reverseTransform($number)
{
if (!$number) {
return null;
}
$issue = $this->om
->getRepository('BundleName:Submission')
->findOneBy(array('id' => $number))
;
if (null === $issue) {
throw new TransformationFailedException(sprintf(
'An Submission with number "%s" does not exist!',
$number
));
}
return $issue;
}
}
This data transformer is initialized in the build form method:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new IntToEntityTransformer($this->em);
$builder->add($builder->create('submission', 'nominees', array(
'expanded' => true,
'multiple' => false
))->addModelTransformer($transformer));
$builder->add('email');
}
I've been fighting this problem with Symfony 2.3. Don't know how it works in 2.1.
In my case I had a entity choice (expanded and multiple) for which I needed to add the entitie's 'descripcion' field, next to the label of each choice.
I solved as follows:
1- created a custom type, whose parent is EntityType, and name 'xxxxxxx_form_reparacionnormalizada'
class ReparacionNormalizadaType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'class' => 'xxxxxxxxx\Entity\TipoReparacion',
));
}
public function getName()
{
return 'xxxxxxx_form_reparacionnormalizada';
}
public function getParent()
{
return 'entity';
}
}
2- register the form type as service as usual
3- created a custom template as follows:
{% block xxxxxxx_form_reparacionnormalizada_widget %}
<ul {{ block('widget_container_attributes_choice_widget') }}>
{% for id, child in form.children %}
<li>
{{ form_label(child, child.vars.label|default(null), { 'in_list_checkbox' : true, 'widget' : form_widget(child) } ) }}
<span>{{ choices[id].data.descripcion }}</span>
</li>
{% endfor %}
</ul>
{% endblock %}
4- in your sonata admin you use your custom type instead of 'entity'
hope it helps
regards
javier