Symfony 3 - Forms choices: How to set 'disabled' = true on "placeholder" - symfony-forms

In Symfony 3, I want the 'placeholder' of a select list menu to appear before any selection is made but to not appear (or not being select-able) among the list of available options for the user.
The function buildForm() of my MyEntityType, extending AbstractType looks like this:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$list = array([array with choices values and descriptions]);
$builder
->add('description',TextType::class, array('label'=>'trans.my_desc'))
->add('list',ChoiceType::class,array(
'label'=>'trans.my_list',
'multiple'=>false,
'choices'=>$list,
'placeholder'=>'trans.do_a_choice',
//'placeholder_in_choices'=>false //this option is not available
)
->add('submit',SubmitType::class,array('label'=>'trans.validate'));
}
When I look at the doc, I see that there is a boolean option placeholder_in_choices (http://symfony.com/doc/current/reference/forms/types/choice.html#field-variables) but this option cannot be set in the [array of options for list] which is under "->add('list',ChoiceType::class,array([array of options for list])" (it throws an error explaining that 'placeholder_in_choices' is not an available option).
Thru my search I found this already existing question close to mine: Symfony how to disable the default option
After reading thru it, I've tried to implement the finishView() function in MyEntityType class:
public function finishView(FormView $view, FormInterface $form, array $options){
var_dump($view->children['list']->vars);
foreach ($view->children['list']->vars['choices'] as $sma) {
if ($sma->value == "") {
$sma->attr['disabled'] = 'disabled';
}
}
}
The problem is that, as it is shown in the var_dump(), $view->children['list']->vars['choices'] does not include the 'placeholder' value or label (trans.do_a_choice), it is not possible hence to attach a 'disabled' attribute to it.
Does anyone has a clue how to have 'trans.do_a_choice' to be displayed as placeholder in the select menu but to not appear (or not being select-able) in the options list?

I am currently using Symfony 4.4 and tried to find a way to solve the issue.
Solution 1: extending the default Symfony form template
This option does not seem to be available, so if you strictly want this result, one method is to override the default form_div_layout.html.twig form template by adding disabled="disabled" to the placeholder option tag.
To achieve this, you need to create a templates/form/form_div_layout.html.twig in your project (the update is on line 8).
{% extends 'form_div_layout.html.twig' %}
{%- block choice_widget_collapsed -%}
{%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%}
{% set required = false %}
{%- endif -%}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{%- if placeholder is not none -%}
<option value=""{% if required and value is empty %} selected="selected" disabled="disabled"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
{%- endif -%}
{%- if preferred_choices|length > 0 -%}
{% set options = preferred_choices %}
{% set render_preferred_choices = true %}
{{- block('choice_widget_options') -}}
{%- if choices|length > 0 and separator is not none -%}
<option disabled="disabled">{{ separator }}</option>
{%- endif -%}
{%- endif -%}
{%- set options = choices -%}
{%- set render_preferred_choices = false -%}
{{- block('choice_widget_options') -}}
</select>
{%- endblock choice_widget_collapsed -%}
Solution 2: using a pure CSS workaround
A pure css solution is a workaround that removes the placeholder option from the list when it's opened.
The original code comes from How to create a placeholder for an HTML5 box
select:required:invalid {
color: #666;
}
select:required option[value=""] {
display: none;
}
option {
color: #000;
}
<select name="drinks" required>
<option value="" disabled selected>Choose a drink</option>
<option value="coffee">Coffee</option>
<option value="tea">Tea</option>
<option value="milk">Milk</option>
</select>

You must override the form theme for your form, or at least the choice_widget_collapsed block. If you use the default form_div_layout, then the related part looks something like this:
{%- if placeholder is not none -%}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
{%- endif -%}
Here you can put the disabled attribute onto the option or any other attribute. Sadly choice_attr or any other option won't work for placeholder, so this is the only way I think.
More info about form themes:
http://symfony.com/doc/current/form/form_customization.html

If I understand correctly you want the placeholder to exist but not be accepted as a selected value?
To do that just add a choice constraint and you'll have the desired behavior. Form would not pass validation if user selects empty or placeholder value.
Something like this:
use Symfony\Component\Validator\Constraints as Assert;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$list = array([array with choices values and descriptions]);
$builder
->add('description',TextType::class, array('label'=>'trans.my_desc'))
->add('list',ChoiceType::class,array(
'label'=>'trans.my_list',
'multiple'=>false,
'choices'=>$list,
'placeholder'=>'trans.do_a_choice',
'constraints' => array(
new Assert\Choice($valuesFromTheListOfChoices)
),
)
->add('submit',SubmitType::class,array('label'=>'trans.validate'));
}
Very important is that the values passed in the assert/Choice match the values from the choices list. Meaning that if you select the placeholder value you must get a validation error.
As for the 'placeholder_in_choices' that option is resolved based on 'placeholder', 'choices' or 'preferred_choices'.
https://github.com/symfony/form/blob/3.1/Extension/Core/Type/ChoiceType.php#L204
It will be set to true if your choice list has an item with empty value.

Related

How to retrieve data attribute from select options of a form select menu using stimulus? [duplicate]

How do I get the selected value from a dropdown list using JavaScript?
<form>
<select id="ddlViewBy">
<option value="1">test1</option>
<option value="2" selected="selected">test2</option>
<option value="3">test3</option>
</select>
</form>
Given a select element that looks like this:
<select id="ddlViewBy">
<option value="1">test1</option>
<option value="2" selected="selected">test2</option>
<option value="3">test3</option>
</select>
Running this code:
var e = document.getElementById("ddlViewBy");
var value = e.value;
var text = e.options[e.selectedIndex].text;
Results in:
value == 2
text == "test2"
Interactive example:
var e = document.getElementById("ddlViewBy");
function onChange() {
var value = e.value;
var text = e.options[e.selectedIndex].text;
console.log(value, text);
}
e.onchange = onChange;
onChange();
<form>
<select id="ddlViewBy">
<option value="1">test1</option>
<option value="2" selected="selected">test2</option>
<option value="3">test3</option>
</select>
</form>
Plain JavaScript:
var e = document.getElementById("elementId");
var value = e.options[e.selectedIndex].value;
var text = e.options[e.selectedIndex].text;
jQuery:
$("#elementId :selected").text(); // The text content of the selected option
$("#elementId").val(); // The value of the selected option
AngularJS: (http://jsfiddle.net/qk5wwyct):
// HTML
<select ng-model="selectItem" ng-options="item as item.text for item in items">
</select>
<p>Text: {{selectItem.text}}</p>
<p>Value: {{selectItem.value}}</p>
// JavaScript
$scope.items = [{
value: 'item_1_id',
text: 'Item 1'
}, {
value: 'item_2_id',
text: 'Item 2'
}];
var strUser = e.options[e.selectedIndex].value;
This is correct and should give you the value.
Is it the text you're after?
var strUser = e.options[e.selectedIndex].text;
So you're clear on the terminology:
<select>
<option value="hello">Hello World</option>
</select>
This option has:
Index = 0
Value = hello
Text = Hello World
The following code exhibits various examples related to getting/putting of values from input/select fields using JavaScript.
Source Link
Working Javascript & jQuery Demo
<select id="Ultra" onchange="run()"> <!--Call run() function-->
<option value="0">Select</option>
<option value="8">text1</option>
<option value="5">text2</option>
<option value="4">text3</option>
</select><br><br>
TextBox1<br>
<input type="text" id="srt" placeholder="get value on option select"><br>
TextBox2<br>
<input type="text" id="rtt" placeholder="Write Something !" onkeyup="up()">
The following script is getting the value of the selected option and putting it in text box 1
<script>
function run() {
document.getElementById("srt").value = document.getElementById("Ultra").value;
}
</script>
The following script is getting a value from a text box 2 and alerting with its value
<script>
function up() {
//if (document.getElementById("srt").value != "") {
var dop = document.getElementById("srt").value;
//}
alert(dop);
}
</script>
The following script is calling a function from a function
<script>
function up() {
var dop = document.getElementById("srt").value;
pop(dop); // Calling function pop
}
function pop(val) {
alert(val);
}?
</script>
var selectedValue = document.getElementById("ddlViewBy").value;
If you ever run across code written purely for Internet Explorer you might see this:
var e = document.getElementById("ddlViewBy");
var strUser = e.options(e.selectedIndex).value;
Running the above in Firefox et al will give you an 'is not a function' error, because Internet Explorer allows you to get away with using () instead of []:
var e = document.getElementById("ddlViewBy");
var strUser = e.options[e.selectedIndex].value;
The correct way is to use square brackets.
Use:
<select id="Ultra" onchange="alert(this.value)">
<option value="0">Select</option>
<option value="8">text1</option>
<option value="5">text2</option>
<option value="4">text3</option>
</select>
Any input/form field can use a “this” keyword when you are accessing it from inside the element. This eliminates the need for locating a form in the DOM tree and then locating this element inside the form.
There are two ways to get this done either using JavaScript or jQuery.
JavaScript:
var getValue = document.getElementById('ddlViewBy').selectedOptions[0].value;
alert (getValue); // This will output the value selected.
OR
var ddlViewBy = document.getElementById('ddlViewBy');
var value = ddlViewBy.options[ddlViewBy.selectedIndex].value;
var text = ddlViewBy.options[ddlViewBy.selectedIndex].text;
alert (value); // This will output the value selected
alert (text); // This will output the text of the value selected
jQuery:
$("#ddlViewBy:selected").text(); // Text of the selected value
$("#ddlViewBy").val(); // Outputs the value of the ID in 'ddlViewBy'
Beginners are likely to want to access values from a select with the NAME attribute rather than ID attribute. We know all form elements need names, even before they get ids.
So, I'm adding the getElementsByName() solution just for new developers to see too.
NB. names for form elements will need to be unique for your form to be usable once posted, but the DOM can allow a name be shared by more than one element. For that reason consider adding IDs to forms if you can, or be explicit with form element names my_nth_select_named_x and my_nth_text_input_named_y.
Example using getElementsByName:
var e = document.getElementsByName("my_select_with_name_ddlViewBy")[0];
var strUser = e.options[e.selectedIndex].value;
Just use
$('#SelectBoxId option:selected').text(); for getting the text as listed
$('#SelectBoxId').val(); for getting the selected index value
I don't know if I'm the one that doesn't get the question right, but this just worked for me:
Use an onchange() event in your HTML, for example.
<select id="numberToSelect" onchange="selectNum()">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
JavaScript
function selectNum() {
var strUser = document.getElementById("numberToSelect").value;
}
This will give you whatever value is on the select dropdown per click.
Using jQuery:
$('select').val();
The previous answers still leave room for improvement because of the possibilities, the intuitiveness of the code, and the use of id versus name. One can get a read-out of three data of a selected option -- its index number, its value and its text. This simple, cross-browser code does all three:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Demo GetSelectOptionData</title>
</head>
<body>
<form name="demoForm">
<select name="demoSelect" onchange="showData()">
<option value="zilch">Select:</option>
<option value="A">Option 1</option>
<option value="B">Option 2</option>
<option value="C">Option 3</option>
</select>
</form>
<p id="firstP"> </p>
<p id="secondP"> </p>
<p id="thirdP"> </p>
<script>
function showData() {
var theSelect = demoForm.demoSelect;
var firstP = document.getElementById('firstP');
var secondP = document.getElementById('secondP');
var thirdP = document.getElementById('thirdP');
firstP.innerHTML = ('This option\'s index number is: ' + theSelect.selectedIndex + ' (Javascript index numbers start at 0)');
secondP.innerHTML = ('Its value is: ' + theSelect[theSelect.selectedIndex].value);
thirdP.innerHTML = ('Its text is: ' + theSelect[theSelect.selectedIndex].text);
}
</script>
</body>
</html>
Live demo: http://jsbin.com/jiwena/1/edit?html,output .
id should be used for make-up purposes. For functional form purposes, name is still valid, also in HTML5, and should still be used. Lastly, mind the use of square versus round brackets in certain places. As was explained before, only (older versions of) Internet Explorer will accept round ones in all places.
Another solution is:
document.getElementById('elementId').selectedOptions[0].value
The simplest way to do this is:
var value = document.getElementById("selectId").value;
You can use querySelector.
E.g.
var myElement = document.getElementById('ddlViewBy');
var myValue = myElement.querySelector('[selected]').value;
Running example of how it works:
var e = document.getElementById("ddlViewBy");
var val1 = e.options[e.selectedIndex].value;
var txt = e.options[e.selectedIndex].text;
document.write("<br />Selected option Value: "+ val1);
document.write("<br />Selected option Text: "+ txt);
<select id="ddlViewBy">
<option value="1">test1</option>
<option value="2">test2</option>
<option value="3" selected="selected">test3</option>
</select>
Note: The values don't change as the dropdown is changed, if you require that functionality then an onClick change is to be implemented.
To go along with the previous answers, this is how I do it as a one-liner. This is for getting the actual text of the selected option. There are good examples for getting the index number already. (And for the text, I just wanted to show this way)
let selText = document.getElementById('elementId').options[document.getElementById('elementId').selectedIndex].text
In some rare instances you may need to use parentheses, but this would be very rare.
let selText = (document.getElementById('elementId')).options[(document.getElementById('elementId')).selectedIndex].text;
I doubt this processes any faster than the two line version. I simply like to consolidate my code as much as possible.
Unfortunately this still fetches the element twice, which is not ideal. A method that only grabs the element once would be more useful, but I have not figured that out yet, in regards to doing this with one line of code.
I have a bit different view of how to achieve this. I'm usually doing this with the following approach (it is an easier way and works with every browser as far as I know):
<select onChange="functionToCall(this.value);" id="ddlViewBy">
<option value="value1">Text one</option>
<option value="value2">Text two</option>
<option value="value3">Text three</option>
<option value="valueN">Text N</option>
</select>
In 2015, in Firefox, the following also works.
e.options.selectedIndex
In more modern browsers, querySelector allows us to retrieve the selected option in one statement, using the :checked pseudo-class. From the selected option, we can gather whatever information we need:
const opt = document.querySelector('#ddlViewBy option:checked');
// opt is now the selected option, so
console.log(opt.value, 'is the selected value');
console.log(opt.text, "is the selected option's text");
<select id="ddlViewBy">
<option value="1">test1</option>
<option value="2" selected="selected">test2</option>
<option value="3">test3</option>
</select>
event.target.value inside the onChange callback did the trick for me.
Most answers here get the value of the "this" select menu onchange by a plain text JavaScript selector.
For example:
document.getElementById("ddlViewBy").value;
This is not a DRY approach.
DRY (three lines of code):
function handleChange(e) {
let innerText = e.target[e.target.options.selectedIndex].innerText;
let value = e.target.value;
/* Do something with these values */
}
Get the first select option:
console.log(e.target[0]); /* Output: <option value="value_hello">Hello innerText</option>*/
With this idea in mind, we dynamically return a "this" select option item (by selectedIndex):
e.target[e.target.options.selectedIndex].innerText;
Demo
let log = document.getElementById('log');
function handleChange(e) {
let innerText = e.target[e.target.options.selectedIndex].innerText;
let value = e.target.value;
log.innerHTML = `<table>
<tr><th>value</th><th>innerText</th></tr>
<tr><td>${value}</td><td>${innerText}</td></tr>
</table>`;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css">
<select id="greet" onchange="handleChange(event)">
<option value="value_hello">Hello innerText</option>
<option value="value_goodbye">Goodbye innerText</option>
<option value="value_seeYou">See you... innerText</option>
</select>
<select id="other_select_menu" onchange="handleChange(event)">
<option value="value_paris">Paris innerText</option>
<option value="value_ny">New York innerText</option>
</select>
<div id="log"></div>
Here is a JavaScript code line:
var x = document.form1.list.value;
Assuming that the dropdown menu named list name="list" and included in a form with name attribute name="form1".
I think you can attach an event listener to the select tag itself e.g:
<script>
document.addEventListener("DOMContentLoaded", (_) => {
document.querySelector("select").addEventListener("change", (e) => {
console.log(e.target.value);
});
});
</script>
In this scenario, you should make sure you have a value attribute for all of your options, and they are not null.
You should be using querySelector to achieve this. This also standardizes the way of getting a value from form elements.
var dropDownValue = document.querySelector('#ddlViewBy').value;
Fiddle: https://jsfiddle.net/3t80pubr/
Try
ddlViewBy.value // value
ddlViewBy.selectedOptions[0].text // label
console.log( ddlViewBy.value );
console.log( ddlViewBy.selectedOptions[0].text );
<select id="ddlViewBy">
<option value="1">Happy</option>
<option value="2">Tree</option>
<option value="3" selected="selected">Friends</option>
</select>
Here's an easy way to do it in an onchange function:
event.target.options[event.target.selectedIndex].dataset.name
<select name="test" id="test" >
<option value="1" full-name="Apple">A</option>
<option value="2" full-name="Ball">B</option>
<option value="3" full-name="Cat" selected>C</option>
</select>
var obj = document.getElementById('test');
obj.options[obj.selectedIndex].value; //3
obj.options[obj.selectedIndex].text; //C
obj.options[obj.selectedIndex].getAttribute('full-name'); //Cat
obj.options[obj.selectedIndex].selected; //true
There is a workaround, using the EasyUI framework with all of its plugins.
You only need to add some EasyUI object that can read from an input as a "bridge" to the drop-down menu.
Example: easyui-searchbox
To the left, the drop-down, to the right, the easyui-searchbox:
...
<input id="ss" class="easyui-searchbox" style="width:300px"
data-options=" searcher:my_function,
prompt:'Enter value',
menu:'#mm'">
<div id="mm" style="width:200px">
<div data-options="name:'1'">test1</div>
<div data-options="name:'2'">test2</div>
</div>
...
...
<script type="text/javascript">
function my_js_function(triggeredByButton = false){
// normal text of the searchbox (what you entered)
var value = $("#ss").searchbox("getValue");
// what you chose from the drop-down menu
var name = $("#ss").searchbox("getName");
...
Mind: the var name is the '1' or '2', that is, the "value of the drop-down", while var value is the value that was entered in the easyui-searchbox instead and not relevant if you only want to know the value of the drop-down.
I checked how EasyUI fetches that #mm name, and I could not find out how to get that name without the help of EasyUI. The jQuery behind getName:
getName:function(jq){
return $.data(jq[0],"searchbox").searchbox.find("input.textbox-value").attr("name");
}
Mind that the return of this function is not the value of the easyui-searchbox, but the name of the #mm drop-down that was used as the menu parameter of the easyui-searchbox. Somehow EasyUI must get that other value, therefore it must be possible.
If you do not want any plugin to be seen, make it as tiny as possible? Or find perhaps a plugin that does not need a form at all in the link above, I just did not take the time.

Comparison string in jinja

how to compare the data from database to compare with value in html with jinja?
I try gender value from db is Male
{% set gender=user.gender %}
{% if gender == 'Male' %}
{% set check = "checked" %}
{% else %}
{% set check = "unchecked" %}
{% endif %}
but the output is Male unchecked and Female also unchecked
I cannot reproduce the issue so it probably means your user variable is not defined as you expect:
import jinja2
t=jinja2.Template(''' {% set gender=user.gender %}
{% if gender == 'Male' %}
{% set check = "checked" %}
{% else %}
{% set check = "unchecked" %}
{% endif %}
''')
for gender in ['Male', 'Female']:
m = t.make_module(vars = {'user': {'gender': gender }})
print(m.check)
prints:
checked
unchecked

Select2 with tags and suggestions

I was using Select2 to have a list of brands and categories, each grouped by <optgroup>.
So far so good, because the list was not changing. Now I have to implement a Product search, which will have no specific values, so you can search for everything you type in.
For example, if the user types in "sho", i want to have:
**Products**
- sho (exactly what the user enters)
**Brands** (suggestions from a list)
- Adidas Shoes
- Nike Shoes
**Categories** (suggestions from a list)
- Shoes for women
- Shoes for men
And as the user types more characters, the sho under Products keeps updating to show what they entered.
The code for the previous version was:
<select id="search_bar">
<option></option>
<optgroup label="Stores">
{% for merchant in all_merchants %}
<option value="{% url %}">{{ merchant.display_name }}</option>
{% endfor %}
</optgroup>
<optgroup label="Categories">
{% for category in all_categories %}
<option value="{% url %}">{{ category.name }}</option>
{% endfor %}
</optgroup>
</select>
I tried enabling tags, by doing tags: true, and it works but not entirely, because if I type in something that matches a brand or a category, the tag will disappear. I.E, if i type "Adidas", it will show only the Adidas under brands (so if i click it, I'm taken to the brand page), but not as a tag that i can click and be taken to the product search page.
Does that make sense?
Ok its first try, i you click on new tag to create, i keep it in the list of firstdropdown and you have propagation in the second dropdown (at least 2 character minimun):
$('#source').select2({
tags:true
});
$('#search').select2({
tags:true,
insertTag:function (data, tag) {
data.push(tag);
},
createTag: function (params) {
return {
id: params.term,
text: params.term,
newTag: true
}
},
matcher: matchCustom,
}).on("select2:select", function(e) {
// if( e.params.data.newTag){
select2_search($("#source"), e.params.data.text);
$(this).find('[value="'+e.params.data.id+'"]').replaceWith('<option selected value="'+e.params.data.id+'">'+e.params.data.text+'</option>');
// }
//uncomment if you want to play the same search
//$("#search").val("0").trigger("change");
});
function matchCustom(params, data) {
// If there are no search terms, return all of the data
if ($.trim(params.term) === '') {
return data;
}
// Do not display the item if there is no 'text' property
if (typeof data.text === 'undefined') {
return null;
}
// Return `null` if the term should not be displayed
return null;
}
function select2_search ($el, term) {
$el.select2('open');
// Get the search box within the dropdown or the selection
// Dropdown = single, Selection = multiple
var $search = $el.data('select2').dropdown.$search || $el.data('select2').selection.$search;
// This is undocumented and may change in the future
$search.val(term);
$search.trigger('input');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/js/select2.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet"/>
<select id ="search" class="myselect" style="width:50%;" >
<option value="0"></option>
</select> <prev><== Type new tag into search</prev>
<br><br><br><br><br><br><br><br>
<select style="width:100%;" id="source" multiple="" tabindex="-1" aria-hidden="true">
<optgroup class="select2-result-selectable" label="Brand" >
<option value="Adidas shoes">Adidas shoes</option>
<option value="Pantalon">Pantalon</option>
<option value="short">short</option>
</optgroup>
<optgroup class="select2-result-selectable" label="Categories" >
<option value="Shoes for men">Shoes for men</option>
<option value="Shoes for women">Shoes for women</option>
<option value="Other things for wommen">Other things for women</option>
<option value="Other things for men">Other things for men</option>
</optgroup>
</select>

Twig checkbox is checked

please how can I do something as follows with twig checkbox
<input type="checkbox" name="checkbox">
{% if checkbox is checked %}
#do_it
{% else %}
#do_that
{% endif %}
help me, please
Checkboxes return string value.
{% if node.field_mycheckbox.value == '1' %}
<p>print 1</p>
{% else %}
<p>print 0</p>
{% endif %}
The controller:
$dispo = $mezzo->getAuDisponibile ();
// table column AuDisponibile is boolean
...
...
return $this-render ('anagrafiche/automezzi.html.twig', ['dispo' => $dispo]);
The template:
{% if dispo %}
<input input type='checkbox' name="idisponibile" value="SI" checked>
{% else %}
<input input type='checkbox' name="idisponibile" value="SI">
{% endif %}
You can check if a form field is checked with in example,
{% if form.field.children.KEY.vars.checked %}
Do something here
{% endif %}
Using it inside a loop.
{% for child in form.field %}
<input type="checkbox" name="checkbox" {{ child.vars.checked == true ? "Checked" }}>
{% endfor %}
or
<input type="checkbox" name="checkbox" {{ form.field.children.KEY.vars.checked ? "Checked" }}>
KEY being the array key.

How do you show a widget content of a piece in a page's index?

I'm struggling with showing some content on Apsotrophe CMS.
I am using apostrophe-pieces to create a description field:
{
name: 'description',
label: 'Description',
type: 'singleton',
widgetType: 'apostrophe-rich-text',
options: {
toolbar: [ 'Bold', 'Italic', 'Link', 'Unlink' ]
}
}
I would like it to show up in the index.html view of a custom page.
However, using {{ apos.singleton(data.piece, 'description', 'apostrophe-rich-text') }} brings up an error and it's unable to render the page. It only works in show.html
In /lib/modules/basics-pages/views/index.html, my code is:
{% extends "apostrophe-pages:outerLayoutBase.html" %}
{% block content %}
<div class="basics-grid">
{% for piece in data.pieces %}
<article>
<h4>{{ piece.title }}</h4>
{% set image = apos.images.first(piece.icon) %}
{% if image %}
<img src="{{ apos.attachments.url(image, { size: 'one-sixth' }) }}" />
{% endif %}
<div class="desc">
{{ apos.singleton(data.piece, 'description', 'apostrophe-rich-text') }}
</div>
</article>
{% endfor %}
</div>
{% endblock %}
Could someone help me with the correct code to use to show the contents of the singleton widget?
As you may know I'm the lead developer of Apostrophe at P'unk Avenue.
This code:
{% for piece in data.pieces %}
Indicates you have a loop variable called piece. That's what you want.
This code:
{{ apos.singleton(data.piece, 'description', 'apostrophe-rich-text') }}
Looks for piece as a property of data and ignores your loop variable.
Remove the data. and you should be good to go.
You'll want to add:
{{ apos.singleton(piece, 'description', 'apostrophe-rich-text', { edit: false }) }}
To avoid inline editing on the index page which would be more confusing than useful.

Resources