How can I change the FormHelper's input template for text input? - cakephp-3.7

I’m trying to change the template for <input type=text/> elements. But when I do it loses the value when in edit context.
I change the FormHelper template from
'templates' => [
'input' => '<input type="{{type}}" name="{{name}}"{{attrs}}/>',
]
to
'templates' => [
'input' => '<my-input type="{{type}}" name="{{name}}"{{attrs}}></my-input>',
]
but it doesn’t get the ‘value’ attribute then and the input field appears blank.
There must be a way of ensuring that the value get's passed in – ideally via attributes of the element as the value attribute.

You earlier implementation should work,
Do make sure that you set the name of the input field similar to the variable name in the database for it to pick the value automatically.
Otherwise you can always set the value attribute of the FormHelper to set it manually.

Related

How to change booleanfields using bootstrap switches?

I want to use the switch button on the bootstrap to operate the model called field, but I don't know how to access it.
class NewBlank(models.Model):
...
blank_on_off = models.BooleanField(default=False)
...
If I have the following booleanfield and can I change the booleanfield by cycling the switch as shown in the picture?
From the HTML specifications, the default value for a checkbox is "on" because you have not included a value attribute
default/on
On getting, if the element has a value attribute, it must return that
attribute's value; otherwise, it must return the string "on". On
setting, it must set the element's value attribute to the new value.
Change your html to
<div class="bootstrap-switch-square">
<input type="checkbox" data-toggle="switch" name="Resend" id="Resend" value="true" />
</div>
so that if its checked, a value of true will be sent in the form data and correctly bound to your boolean property (if unchecked, no value will be sent and the property will be its default (false) value
originaly answered

What does the 'name' parameter do in flask-wtf's field definition?

As per Flask_WTF documentation, a 'name' is required when defining a field, as done in the example below:
class MyForm(FlaskForm):
field_name = StringField('***name***')
I couldn't find any explanation of how this parameter is used. It's not required to render the field in the HTML file, where the Jinja2 syntax used is:
{{ form.field_name() }}
It's also not required in Python to retrieve the value inputted by the user, where the syntax used is:
value = MyForm.field_name.data
In fact my code works perfectly well even if I were to completely remove the 'name' parameter when defining the field. So, can anyone throw a light on where this parameter is used?
It's the label of field.
you can use it like this:
{{ form.field_name.label }}

Print newly persited entity's id right after form submission using CollectionType

Shortly said
On submission of a new item, Symfony handles POST datas but newly persisted items do not have their id populated in their corresponding hidden field value attribute, the value attribute is missing instead.
Surgery:
I've implemented some add/edit/remove feature to let users manage a pool of "City" entities, using a CollectionType.
When a new city is added:
I made sure every existing entry has an hidden field holding the entity's id (pk), along with editable regular properties in order to update correctly existing instances
On form submission, datas are available [ok]
Persist loop and following flush successfully update database [ok]
Form gets rendered again with the newly added city
All is working except the fact that any new submitted city has their hidden field missing «value» attribute.
I read things like
Accessing objects getters right after flush returns the corresponding up to date properties. Newly inserted records ids get populated …
So I expected Doctrine to update newly persisted city objects upon flush, but it looks like nothing is happening. Form seems not to be aware of new insertions. Is this because of Forms datas immutability after a request gets handled ?
Note: At least, when reloading the page (reach the same URL without posting datas twice), hidden fields finally have their attribute value with corresponding entity's id printed.
Could someone help me spot what needs to be done here so that hidden fields (of newly inserted items) get correctly rendered (with «value» attribute containing expected entity id) right after submission ?
Controller …
<?php
// ...
/**
* #Route("/cities", name="admin_config_cities")
*/
public function configureCitiesAction(Request $request)
{
# Retrieving existing cities
$em = $this->getDoctrine()->getManager();
$cities = $em->getRepository('AppBundle:City')->findAll();
# Associate cities ids with corresponding objects
$sorted = [];
array_walk($cities, function ($value, $key) use (&$sorted) {
$sorted[ $value->getId() ] = $value;
});
# Initialize form
$citiesForm = $this->createForm(
CollectionType::class,
$cities,
[
'entry_type' => CityType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
# I thought "mapped" option would do the trick.
# worse, seems to do nothing
'mapped' => true,
'label' => false,
'entry_options' => [
'label' => false,
'by_reference'=>true
]
]
);
if ($request->isMethod('POST')) {
$citiesForm->handleRequest($request);
if ($citiesForm->isValid()){
# Persist any submitted datas
foreach( $citiesForm->getData() as $city ){
$id = $city->getId();
if ($id && array_key_exists($id,$sorted)) {
unset($sorted[$id]);
}
$em->persist($city);
}
# Remove discared cities
foreach( $sorted as $removed ){
$em->remove($removed);
}
$em->flush();
}
}
# TODO: find the way to make newly added cities to be rendered
# along with their ID available inside an hidden field's attribute
# right after submission (without the need of a refresh)
return $this->render('AppBundle:admin:config/cities.html.twig', [
'form' => $citiesForm->createView()
]);
}
CityType contains an hidden field
//…
$builder->add( 'id', HiddenType::class, [ 'required'=>false ])
//…
Associated Template
{# … #}
{{ form_start(form) }}
<div data-prototype="{{ form_widget(collection.vars.prototype)|e }}">
{% for item in collection %}
{{ form_widget(item) }}
{% endfor %}
<p>
<a class="btn btn-default btn-sm" title="{{ 'button-add-title'|trans }}">{{ 'button-add-caption'|trans }}</a>
</p>
</div>
<p class="text-right">
<button type="submit">Submit</button>
</p>
{{ form_end(form) }}
Hopping this is clear enough, thank you.
EDIT
by_reference is set to true inside collection's entry_options.
Tests I've done say: it only has impact there. True make it possible to update corresponding (existing) records in DB. On the other hand, false prevents mapping to be done therefore resulting in duplicate entries in database.
Setting by_reference on the collection itself simply seems to do nothing at all.
That said, new records are actually persisted, but modification of this newly created element leads to random behaviour (deleted because of allow_delete, duplicate entry issued). Still developper tool DOM tree does not show hidden field's value attribute, neither do navigator source shortcut Ctrl+u. Value attribute magically appears once a fresh GET request is made.
There are definitly things I do not understand here :/.
In the end, the only way I found to make sure form is rendered with hidden fields correctly populated is to command $this->redirect($this->generateUrl($_route)); after flush().

Meteor/Jade: Use variable in template ID

How can I use a variable like {{_id}} within a template id tag? It renders as text inside the tag instead of part of the ID name.
Template:
div.element-versions#element_{{name}} // "name" evaluates to "001_version"
Renders as:
<div class="element-versions" id="element_">001_version</div>
Instead of:
<div class="element-versions" id="element_001_version"></div>
.element-versions(id='element_{{name}}')
Where 'name' can be a helper or a field of the current data context. Jade defaults to using divs, so you can leave off 'div' from your element tag as well if you want to.

Using "record" in attributes Django Tables 2

I'm moving my tables to django-tables2. By now is almost everything working ok, but now I have a problem.
In my current version i use checkboxes to select items
<td><input type="checkbox" class="checkbox_delete" name="event" id="event.id"
value="{{ event.id }}" />
this way in the view i can recover the event.id using request.POST.getlist('event')
Now I'm trying to add the "value" attribute to a CheckBoxColumn
select = tables.CheckBoxColumn(attrs={'td__input': {'class': 'checkbox_delete', 'name': 'event', **'value': [A('id')]**}, 'th__input': {'id': 'selectAll'}},
empty_values=())
I've been playing with the Accesor and the record.id which I use in a templateColumn.
How can I pass the id to the value attribute??
You can simply do something like this:
id = tables.CheckBoxColumn()
This way, the column will be rendered like this
<input type="checkbox" name="id" value="X">
where X will be the value of the id field.
Now for a more complete answer:
You can add td__input to override some defaults but I don't believe what you can set it to different values for each column ! By checking the source:
https://github.com/bradleyayers/django-tables2/blob/master/django_tables2/columns/checkboxcolumn.py
you will see that in the render method in CheckBoxColumn will create an AttributeDict containing the attributes from input, td__input and some defaults, like this:
def render(self, value, bound_column): # pylint: disable=W0221
default = {
'type': 'checkbox',
'name': bound_column.name,
'value': value
}
general = self.attrs.get('input')
specific = self.attrs.get('td__input')
attrs = AttributeDict(default, **(specific or general or {}))
return mark_safe('' % attrs.as_html())
So the attrs you define will be the same in all columns since attrs.as_html will just convert the 'x':'y' dict entries to x=y...
So if you want to have total control and do whatever you like with the values for each column, just subclss CheckBoxColumn and override render (left as an excersise to the reader).
Update
Also, a very nice thing about your own render method is that you don't need to define the same parameters as the base one. This is because django-tables2 uses the getargspec function to find out which arguments your render expects and pass them to the render method. So, if you take a look at the https://github.com/bradleyayers/django-tables2/blob/master/django_tables2/rows.py you will see that the available parameters that can be passed to render, along with their values are:
available = {
'value': value,
'record': self.record,
'column': bound_column.column,
'bound_column': bound_column,
'bound_row': self,
'table': self._table,
}
So, for instance you can define your render method like:
def render(self, value, bound_column, record):
to also pass the record to it.
I found another solution here How to get information from Django_tables2 row?
Just need to define select = tables.CheckBoxColumn(accessor='pk') and it add the value as the record.id