radio buttons in list don't group - forms

I've got a pretty nasty problem here!
I have an <ul> with a group of input in every <li>. In every list element there is a radio button and I want to group them together to make them toggle when clicked.
The problem is that the radios don't connect! if I click two of them they get both checked!
Here's the code: http://jsfiddle.net/bakaburg1/Djq5q/1/
To notice: this is the code for a wordpress custom field.
Many Thanks!
EDIT1:
it's important that the fields in every list element remain connected so that on the PHP side i got a data structure as such:
array (
0 =>
array (
'answer' => 'answer1',
),
1 =>
array (
'answer' => 'answer2',
),
2 =>
array (
'is_right' => 'on',
'answer' => 'answer3',
),
3 =>
array (
'answer' => 'yiuyiuyiuj',
),
)
EDIT2:
for the time being I patched the issue with some jQuery:
jQuery('.mm_ps_answers input:radio').click(function(){
jQuery(this).parents('ul').find('input:radio').not(this).attr('checked', false)
})
Not sure the most elegant solution though, feel free to comment (not answer) on this snippet too!
EDIT3:
I solved the problem by giving three different names to the fields, and then merging the POSTed data in one array to be then serialized and saved in the database.
<li>
<a class="mm_ps_move button"><img src="http://localhost:8888/minimamedicamenta/wp-content/themes/minima/img/move.png"></a>
<a class="mm_ps_delete_answer button">Delete Answer</a>
<input type="radio" class="mm_ps_is_right" name="mm_ps_answers_is_right[]">
<input type="text" name="mm_ps_answers_input[]" value="">
<input type="hidden" name="mm_ps_answers_impressions[]">
<span class="mm_ps_impressions">impressions: <span>0</span></span>
</li>
Another problem poped up though... while the POSTed data in the back end for the text input fields is a well ordered array with a value for every field, also the empty ones, the radiobutton send only one value, so i have no idea of wich radio in wich list element has been checked, any help on this? Here's is the data in the POST for the three inputs (values are random strings):
[04-Aug-2012 17:18:45] Line (in ):
array (
0 => 'cvxcv',
1 => 'vs',
2 => '',
3 => 's',
)
[04-Aug-2012 17:18:45] Line (in ):
array (
0 => 'on',
)
[04-Aug-2012 17:18:45] Line (in ):
array (
0 => '',
1 => '',
2 => '',
3 => '',
)
EDIT4:
I patched the issues with a javascript that assign an incremental numerical value to the radio buttons on every action that modify the list (sorting, adding, deleting elements). Not very clean although.

<ul class="mm_ps_answers manage_list ui-sortable">
<li>
<input type="radio" name="SameName">
<input type="text" name="mm_ps_answers[0][answer]" value="jkjhk">
<span class="mm_ps_impressions">impressions: </span>
</li>
<li>
<input type="radio" name="SameName">
<input type="text" name="mm_ps_answers[1][answer]" value="lknjlk">
<span class="mm_ps_impressions">impressions: </span>
</li>
<li>
<input type="radio" name="SameName">
<input type="text" name="mm_ps_answers[2][answer]" value="òklkjl">
<span class="mm_ps_impressions">impressions: </span>
</li>
<li>
<input type="radio" name="SameName">
<input type="text" name="mm_ps_answers[3][answer]" value="p09i0i">
<span class="mm_ps_impressions">impressions: </span>
</li>
The property that makes a browser to toggle them is the NAME of the RadioButton. Name all those radio buttons the same(each group should have same name) and they will toggle.

If it's not possible for to use the name attribute for one reason or another (for example your name attribute is populated dynamically - which I suspect it is), you could use jQuery to toggle the checkboxes:
$(document).ready(function() {
$('input[type="radio"]').click(function() {
$('input[type="radio"]').prop('checked', false);
$(this).prop('checked', true);
});
});

To group radio buttons together you must specify the same value in the name attribute.
ex. (from W3Schools)
<form action="">
<input type="radio" name="sex" value="male" /> Male<br />
<input type="radio" name="sex" value="female" /> Female
</form>
Edit:
To keep the order you were planning in the jsFiddle link you provided I would recommend you make an iterative statement on one list item :
(sorry for incorrect php code but i haven't used it in a long time)
foreach($answer as $value){
<li>
<input type="radio" name="answer" value="$value[is_right]">
<input type="text" name="$value[answer]" value="jkjhk">
<span class="mm_ps_impressions">impressions: </span>
</li>
}

Related

Somfony CollectionType: Influces of ID, Name + DOM position on sort order?

I am working on a Symfony 3.4 based project and wonder what influence the id and name attributes of CollectionType form elements, as well as their position within the DOM have on the sort order.
I was not able to find anything about this in the documentation. My tests show that only the name is important but I would like to confirm this to not break anything.
Details:
Assume we have a very simple ToDoItem entity with only two properties date and value.
A CollectionType should be used to let the user edit a list of these items within a form.
The form allows to remove existing items, add new items and to re-order the items using JS
The DB might contain the following items:
id date value
0 2020-06-01 do something
2 2020-06-02 do nothing
This would be rendered to a form like this:
...
<ul>
<li id="todo_items_0>
<input type="text" id="todo_items_0_date" name="todo[items][0][date]" value="2020-06-01">
<input type="text" id="todo_items_0_value" name="todo[items][0][value]" value="do something">
</li>
<li id="todo_items_1>
<input type="text" id="todo_items_1_date" name="todo[items][1][date]" value="2020-06-01">
<input type="text" id="todo_items_1_value" name="todo[items][1][value]" value="do nothing">
</li>
</ul>
Test Result 1:
Changing the DOM order has NO effect on the sort / DB order
...
<ul>
<li id="todo_items_1>
<input type="text" id="todo_items_1_date" name="todo[items][1][date]" value="2020-06-01">
<input type="text" id="todo_items_1_value" name="todo[items][1][value]" value="NEW VALUE 1">
</li>
<li id="todo_items_0>
<input type="text" id="todo_items_0_date" name="todo[items][0][date]" value="2020-06-01">
<input type="text" id="todo_items_0_value" name="todo[items][0][value]" value="NEW VALUE 0">
</li>
</ul>
// Result
id date value
0 2020-06-01 NEW VALUE 0
2 2020-06-02 NEW VALUE 1
Test Result 2:
Changing the id has NO effect on the sort / DB order
...
<ul>
<li id="todo_items_1>
<input type="text" id="todo_items_1_date" name="todo[items][0][date]" value="2020-06-01">
<input type="text" id="todo_items_1_value" name="todo[items][0][value]" value="NEW VALUE 0">
</li>
<li id="todo_items_0>
<input type="text" id="todo_items_0_date" name="todo[items][1][date]" value="2020-06-01">
<input type="text" id="todo_items_0_value" name="todo[items][1][value]" value="NEW VALUE 1">
</li>
</ul>
// Result
id date value
0 2020-06-01 NEW VALUE 0
2 2020-06-02 NEW VALUE 1
BUT: Changing the id might have other side effects. For example I am using a jQuery Datepicker which does not work anymore when the id is changed.
Test Result 3:
Changing the name DOES change sort / DB order.
...
<ul>
<li id="todo_items_0>
<input type="text" id="todo_items_0_date" name="todo[items][1][date]" value="2020-06-01">
<input type="text" id="todo_items_0_value" name="todo[items][1][value]" value="NEW VALUE 0">
</li>
<li id="todo_items_1>
<input type="text" id="todo_items_1_date" name="todo[items][0][date]" value="2020-06-01">
<input type="text" id="todo_items_1_value" name="todo[items][0][value]" value="NEW VALUE 1">
</li>
</ul>
// Result
id date value
0 2020-06-02 NEW VALUE 1
2 2020-06-01 NEW VALUE 0
While this does work in my case one should note, that this actually does not change the sort order but the order of the elements in the DB while keeping the id the same. So Entity 0 now contains the information about item1 and Entity 1 the information about item2...
Conclusion:
The sort order within the CollectionType field is only effected by the name attribute
Changing the id attribute or the DOM position has no effect.
It seems to be no problem if id and name attributes represent different indexes.
So the big question is: Is this the intended Symfony behaviour which is documented somewhere or is this only an unintentional result which could change with any new Symfony release?
The default order of a collection is by id but the order can be overwritten. I would add a position value to your ToDoItem and change that with JQuery to reoder the Collection. Your current solution is more of a hack and you should not keep using it.
/**
* #OneToMany(targetEntity=ToDoItem::class)
* #OrderBy({"position" = "ASC"})
*/
private $toDoItems;

Forms testing Angular 4

I have done a small Web App in Angular 4 and I'm now trying to test it.
Here is what I would like to test :
<form class="navbar-form navbar-left" (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" ngModel name="name" pattern=".{2,}" required #name="ngModel">
</div>
<button type="submit" class="btn btn-default" [disabled]="!f.valid">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>
<span class="help-block help" *ngIf="!name.valid && name.touched ">Please enter at least two characters</span>
</form>
At first, I would just like to test if the form is really invalid (and then I cannot click on the submit button) if thye word entered in the input is less than 2 characters.
Here is the test code I have written
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should disable submit if word<2',()=>{
const compiled = fixture.nativeElement;
const input = fixture.debugElement.query(By.css('input'));
input.nativeElement.value='b';
input.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
//console.log(compiled.querySelector('input').textContent);
//console.log(compiled.querySelector('.ng-valid'));
expect(compiled.querySelector('.ng-valid')).toBe(null);
});
The textContent of the input is modified properly but the form is still valid. However, when I use the webapplication, I can't submit the form is the word is less than two characters.
I feel like the word in the input doesn't really "reach" the form in the test. I've tried a lot of different things so any help would be great !

Foundation 5 & Abide: a custom validator for a set of checkboxes?

I would like to create a validator for abide for a set of checkboxes.
Let's consider a set of 5 checkboxes. The user is asked to check 3 max, and at least 1.
So, here is my work-in-progress code:
<div data-abide-validator='checkboxes' data-abide-validator-values='1,3'>
<input type="checkbox"/>
<input type="checkbox"/>
<input type="checkbox"/>
<input type="checkbox"/>
<input type="checkbox"/>
</div>
<script>
$(document).foundation({
validators: {
checkboxes: function(el, required, parent) {
var countC = el.find(':checked').length;
alert(countC);
}
}
});
</script>
At this point, I just try to count the checked inputs. But it seems I can't even trigger the validator... I think I could manage to code my validation stuff if only I could figure out how to trigger it.
Indeed I didn't find many examples of the custom validator, and the official doc did not help me much.
Your HTML markup is not really "correct" for abide. You should be attaching the data-abide-validator attribute to the inputs, not the parent div. Additionally, you need some better markup so abide's default error display can work (and some better use of foundation's grid system to lay it out). I would point you toward the Abide Validation Page on Zurb's site for some examples of form markup.
I've taken the liberty of restructuring your markup to be something that is more becoming of a foundation layout:
<form action="/echo/html/" method="POST" data-abide>
<div class="row">
<div class="small-12 columns checkbox-group" data-abide-validator-limit="1,3">
<label>Check some boxes</label>
<small class="error">You have checked an invalid number of boxes.</small>
<ul class="small-block-grid-3">
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="1" /> 1
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="2" /> 2
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="3" /> 3
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="4" /> 4
</label>
</li>
<li>
<label>
<input type="checkbox" data-abide-validator="checkbox_limit" value="5" /> 5
</label>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<button type="submit">Submit</button>
</div>
</div>
</form>
As to your JS code. It's not correct either. You need to address the abide -> validators namespace of the options, not just validators. I've rewritten your JS code to not only do that, but give the desired effect you wanted:
$(document).foundation({
abide: {
validators: {
checkbox_limit: function(el, required, parent) {
var group = parent.closest( '.checkbox-group' );
var limit = group.attr('data-abide-validator-limit').split(',');
var countC = group.find(':checked').length;
if( countC >= limit[0] && countC <= limit[1] ) {
group.find('small.error').hide();
//return true so abide can clear any invalid flags on this element
return true;
} else {
group.find('small.error').css({display:'block'});
//return false and let abide do its thing to make sure the form doesn't submit
return false;
}
}
}
}
});
In order to check adjacent elements when doing custom validation, you need to have something to target. The el variable in the validation function will be the DOM element of the input/field that is being validated. The required variable will tell you if the field is flagged as being required or not (boolean). The parent variable will be set to the "parent" of the field. I say "parent" because although the label tag is technically the parent of the input element, abide is smart enough to realize that the label is part of the field's element structure and skip over it to the li element instead.
From there, you need a way to identify a common parent. So I added the checkbox-group class to whatever element I decided to make the "parent" of all the checkboxes in the group. This is not a Foundation or Abide "magic" class, but rather something of my own creation for use in the validation function.
From there, you can easily trace the few lines of the validation function to see the workflow: Find the group container object, parse the limits off the container's data-abide-validator-limits attribute, count the number of checked inputs in the container, check if the number checked is between the limits, display/hide the error message and return true/false so abide knows if the field validated or not.
I've got a working Fiddle of it if you care to check it out yourself ;) Hopefully this was informative for you, and I wish you the best of luck playing with the awesome that is Foundation!

Example of jQuery Mobile site with conditional/branching questions

I'm trying to create a JQM survey with branching questions--i.e. in a survey with questions 1-3, if you choose a particular answer on question 1, a question is dynamically added between questions 1 and 2.
UPDATE: I made an attempt ( https://dl.dropbox.com/u/17841063/site2/index-c1.html#page2 ) that works by matching the value of a radio button to the name of a hidden div--if there's a match, it unhides the div. The problem right now is that if you change your answer back to an option that wouldn't trigger the conditional question, it doesn't re-hide. For example, clicking No or Unsure in question A1 causes question A2 to appear, but if you then click Yes in A1, A2 still remains...
<script type="text/javascript">
// Place in this array the ID of the element you want to hide
var hide=['A2','A4'];
function setOpt()
{
resetOpt(); // Call the resetOpt function. Hide some elements in the "hide" array.
for(var i=0,sel=document.getElementsByTagName('input');i<sel.length;i++)
{
sel[i].onchange=function()
{
if(this.parentNode.tagName.toLowerCase()!='div')
resetOpt(); // Hides the elements in "hide" array when the first select element is choosen
try
{
document.getElementById(this.value).style.display='';
}
catch(e){} ; // When the value of the element is not an element ID
}
}
}
window.addEventListener?window.addEventListener('load',setOpt,false):
window.attachEvent('onload',setOpt);
function resetOpt()
{
for(var i=0;i<hide.length;i++)
document.getElementById(hide[i]).style.display='none'; // Hide the elements in "hide" array
}
</script>
Here's are the radio buttons that use the script above:
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>(Question A1) A prominent accident smokes on top of the blessed reactionary?</legend>
<input type="radio" name="aaa" id="aaa_0" value="notA2" />
<label for="aaa_0">Yes</label>
<input type="radio" name="aaa" id="aaa_1" value="A2" />
<label for="aaa_1">No</label>
<input type="radio" name="aaa" id="aaa_2" value="A2" />
<label for="aaa_2">Unsure</label>
</fieldset>
</div>
<div id="A2" data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<legend>(Question A2) Does a married composite remainder the shallow whistle??</legend>
<input type="radio" name="bbb" id="bbb_0" value="" />
<label for="bbb_0">Yes</label>
<input type="radio" name="bbb" id="bbb_1" value="" />
<label for="bbb_1">No</label>
<input type="radio" name="bbb" id="bbb_2" value="" />
<label for="bbb_2">Unsure</label>
</fieldset>
</div>
If anyone has ideas about fixing this, or examples of other ways to do branching forms, I'd be very grateful!
Thanks,
Patrick
I played around a little bit with your example, removed all your plain JavaScript and added some jQuery Mobile style script, see working example here
<script>
$("input[type='radio']").bind( "change", function(event, ui) {
var mySelection = $('input[name=aaa]:checked').val();
//alert(mySelection);
if (mySelection == "A2") {
$('#A2').removeClass('ui-hidden-accessible');
} else {
$('#A2').addClass('ui-hidden-accessible');
};
});
</script>

Zend Form Display Group Decorators

I am trying to figure our how to remove the label from a display group, when you look at the
markup below you will see that there is a dt with the id address-label and the following dd, I want to remove these but keep
the fieldset.
To add the display group I am using this $this->addDisplayGroup(array(...), 'legend' => 'address'); within
my form init class after I have added each of the elements. Are there some decorators I can play with to remove
the element I dont want?
<form id="CreateAddress" enctype="application/x-www-form-urlencoded" action="" method="post">
<dl class="zend_form">
<dt id="address-label"> </dt>
<dd id="address-element">
<fieldset id="fieldset-address">
<legend>Address</legend>
<dl>
<dt id="addressLine1-label">
<label for="addressLine1" class="required">Address Line 1</label>
</dt>
<dd id="addressLine1-element">
<input type="text" name="addressLine1" id="addressLine1" value="">
</dd>
...etc...
</fieldset>
</dd>
...buttons...
</dl>
</form>
Thanks,
Martin
If you want to apply it to all Zend Form Display Groups defined (for a particular form), a neater way is:
$form->setDisplayGroupDecorators(array(
'FormElements',
'Fieldset',
));
NOTE: this only alters previously defined Display Groups.
The removeDecorator parameter Zend_Form_Decorator_DtDdWrapper didn't work so I used:
$group = $form->getDisplayGroup('the name of the group');
$group->removeDecorator('DtDdWrapper');
So that you don't have to manually remove the DtDd's from each display group individually, you can use:
foreach ($this->_displayGroups as $dg){
$dg->removeDecorator('DtDdWrapper');
}
So what's the deal?
$group = $form->getDisplayGroup ('the name of the group');
$group->removeDecorator ('Zend_Form_Decorator_DtDdWrapper');