CakePHP 3.x checkbox formatting issue - cakephp

This may seem obvious to some of you, but I really am struggling to find a straight answer. I've generally googled, as well as read both the CakePHP manual and the API for an answer to the following question:
When creating an input, the following code creates the following outputs:
// in the view
echo $this->Form->input('notes');
// resultant html
<div class="input textarea">
<label for="notes">Notes</label>
<textarea id="notes" rows="5" name="notes"></textarea>
</div>
Note: this is consistent across most input types; and because it's consistent it's great for formatting.
However, with a checkbox:
//In the view
echo $this->Form->input('ticket_required',
['type' => 'checkbox']
);
// resultant HTML
<div class="input checkbox">
<input type="hidden" value="0" name="ticket_required">
<label for="ticket-required">
<input id="ticket-required" type="checkbox" value="1" name="ticket_required">
Ticket Required</label>
</div>
[Note: I understand the need/desire for the hidden field]
Now.. surely it can't be an uncommon requirement to simply want the same format approach as every other standard input?
My question - how do I make CakePHP create a checkbox element as follows:
// desired HTML
<div class="input checkbox">
<input type="hidden" value="0" name="ticket_required">
<label for="ticket-required">
Ticket Required</label>
<input id="ticket-required" type="checkbox" value="1" name="ticket_required">
</div>
To be clear: the order of visible elements is the same as other generated elements (label before input, and all encased in the wrapping div).
Please note.. i have tried the 'nestedInput' => false option. This actually gets rid of the checkbox input entirely from the div.
I can't understand why this isn't done that way... but even if it was, I can't fathom why this isn't an obvious question for the documentation.
Oh well.. hopefully someone can help me here.
Thanks in advance.
Rick

I would have thought the nestedInput would work but even if it did, you don't want to add that to every input you create throughout the website.
CakePHP 3 uses string templates to build form controls. You can modify them to suit your needs.
By default the checkbox is using the nestingLabel template so if you want to stop all inputs from being nested you can change the template.
// src/View/AppView.php
$this->loadView('Form', [
templates => [
'nestingLabel' => '<label{{attrs}}>{{text}}</label>{{hidden}}{{input}}'
],
// [More helper default config overrides][2]..
])
For more control over your helpers you can create your own that extends one of the core helpers.

Related

Wrong behavior while checking radio buttons in a Loop (using Angular2)

I'm working on an Angular2 project & currently i'm stuck with a Quizz module, so illustrating the problem ; when a candidate wants to pass a test he will get that test with some questions ; every question has 4 propositions with radio buttons and he should answer merely by checking one of them for every question. here is the HTML snippet of what i'm talking about :
<div *ngFor="#qt of listQuestion">
<h3 class="uk-accordion-title" >{{qt.wordingQ}}</h3>
<div class="uk-accordion-content">
<input type="radio" id="radio_demo_1" />
<label for="radio_demo_1"> <b>{{qt.lpo[0]}}</b></label> <br><br>
<input type="radio" id="radio_demo_2" />
<label for="radio_demo_2"><b>{{qt.lpo[1]}}</b></label><br><br>
<input type="radio" id="radio_demo_3" />
<label for="radio_demo_3"> <b>{{qt.lpo[2]}}</b></label> <br><br>
<input type="radio" id="radio_demo_4" />
<label for="radio_demo_4"><b>{{qt.lpo[3]}}</b></label>
</div> </div>
Where the listQuestion is a list of Question entities which each one of them has a wording and a list of propositions (lpo), in that way i cannot check only one radio button for every question as it is shown below :
I tried to remove the id in the <input> tags and it still the same problem , I've changed the id by name and give the same name for all tags thus, I could check only one proposition but when moving to another question and checking a new proposition , the first one will be cleared.
Any help Please ?
Your problem is that the way you currently do it, you have a single radio group for all questions. You can solve it by creating radio element name attributes dynamically. Something like this:
<h3 class="uk-accordion-title" >{{qt.id}}</h3>
<input type="radio" id="radio_demo_{{qt.id}}_{{index$}}" name="radio_demo_{{qt.id}}_{{index$}}" />
<label for="radio_demo_{{qt.id}}_{{index$}}"> <b>{{qt.lpo[0]}}</b></label> <br><br>
{{qt.id}} (or any other qt property that uniquely identifies the question) is the key here.
This way, you'll have a separate radio group for each question, because group names won't intersect.

Angular-formly custom Validation on multiple fields on a repeat section

I was trying to create a custom validator for angular-formly repeated section.
The form should be valid only if the sum of the percentage inputs is 100. So for example if repeat section has 2 fields 50 and 50 should be a valid option or 25 and 75 and so on.
While I was working on a JSbin in order to do that I found out that the repeated model is not actually updated onKeydown. Therefore iterating though all the repeat section values and calculating their sum is not possible.
I also tried with modelOptions: { updateOn: 'Keydown' } with no success. It actually makes the validator not to get called at all.
UPDATE
I came up with the following solution from the matching fields example.
Unfortunately it appears that the example its self has a problem.
Play with the following JSbin and see that there are many cases where the validator gets called and returns true but the field/fields still remain red (indicating they have a problem).
Here is the JSBin.
Apologies since I didn't had the time to get back on this one. It has an open issue on GitHub for 2 months now. I fixed it temporary by using 7.1.2 version of angular-formly and just waiting for an update. The updated version of JSBin I have on the question should be working.
UPDATE
Since I had time and fixed this with repeat section (with a hacky way of course) I tough I should post it in case someone else is looking for this.
(note: the solution doesn't depend on formly version)
Working JSBin
You made a typo while using modelOptions: { updateOn: 'Keydown' } the Keydown's k should be small case instead of uppercase, after fixing typo its working as expected. Also the ngModelOptions accept all event name in small case like keydown, keyup, blur, focus, etc.
modelOptions: { updateOn: 'keydown' }
Forked Plunkr
To create your own checks is best used reusable components, for example directive use-form-error.
Look at the example of jsfiddle.
<div ng-form="testForm" use-form-error="sumNot100" use-error-expression="input_1+input_2+input_3!=100">
<label>Sum of all input must be 100</label>
<br>
<label>Input 1</label>
<input ng-model="input_1" type="number" name="input_1">
<label>Input 2</label>
<input ng-model="input_2" type="number" name="input_2">
<label>Input 3</label>
<input ng-model="input_3" type="number" name="input_3">
<div ng-messages="testForm.$error" class="errors">
<div ng-message="sumNot100">
Sum of all input not equal 100
</div>
</div>
<button ng-disabled="testForm.$invalid">
Submit
</button>
</div>

Form input arrays in angular

I am learning Angular.js and i've come to a problem that should probably be simple, but I can't seem to find an answer on.
I want to create form inputs with the value of "connectedTeams", like this in html:
<input type="text" name="connectedTeam[]">
<input type="text" name="connectedTeam[]">
<input type="text" name="connectedTeam[]">
I have tried the following in angular...
<input type="text" name="connectedTeams[]" class="form-control" ng-model="user.connectedTeams">
...but it is binding the same value to all 3 inputs. I know in my mind that this makes sense, but I can't seem to figure out how to tell it that ng-model is user.connectedTeams.[] (user > connectedTeams > add to an array.
I hope this makes sense enough for someone to provide a quick answer.
ng-model="user.connectedTeams[0]"
ng-model="user.connectedTeams[1]" and so on
You can put it in a ngRepeat, so you don't need to repeat your code like above.
FYI, name is only used for validation in Angularjs.

Angular form.fieldName.$invalid not working inside ng-class attribute

I have already solved this problem, but it took me a while to realize what I did wrong. It's a very simple mistake, but I figured I'd post it here in hopes I can save someone else some work in case they run across the same mistake.
I was trying to use simple Angular validation to set a class on an input field based on whether it was valid. I failed to realize it wasn't working because I specified the name of my form with ng-form. So using $scope.form or the actual value of name attribute of the form did not work. Of course, the examples below are simplified and a much larger form could make this mistake much harder to recognize.
Here is a failed example:
<form name="myForm" ng-form="form1">
<input type="text" name="myField" ng-class="error: myForm.myField.$invalid"/>
</form>
Here is a successful example:
<form name="myForm" ng-form="form1">
<input type="text" name="myField" ng-class="error: form1.myField.$invalid"/>
</form>

Angular.js sanity check: Services vs. Factories vs. Controllers... + Directives + Behavior

This article about when to use directives, services and controllers, as awesome and helpful as it is... has me massively confused about everything I think I know about the ideal structure of an angular application and I just need a sanity check:
If you have two inputs:
<label><span>false</span>
<input type='radio' value='false' ng-value='false' ng-model='thing.exists' />
</label>
<label><span>true</span>
<input type='radio' value='true' ng-value='true' ng-model='thing.exists' />
</label>
that are part of a larger form, which will in turn submit to pull in another form... and that information will later be shown for review, is this the correct way to architect that:
TLDR: Flow of execution:
ng-model="thing.exist" ==> thing ==> ThingController ==> a service ==> ...details... ==> getDetails?
Right now I have:
<div ng-controller='ThingController as thing'>
<fieldset>
<label><span>Doesn't exist</span>
<input type='radio' value='false' name='checkExist'
ng-value='false' ng-model='thing.exists' />
</label>
<label><span>Does exist</span>
<input type='radio' value='true' name='checkExist'
ng-value='true' ng-model='thing.exists' />
</label>
</fieldset>
<!-- ... -->
</div>
When the input changes,
I should use ng-change on the inputs to trigger the behavior (like the addition of a directive)... right (via a controller)?
I should use then controller to add the result of the ng-change to a service? Like... passing the model value (thing.exists) to a service so I can use that value later?
As a complication factor- this application uses Require.js to manage dependencies.
(Actually, the article itself isn't the source of my confusion- it's the comments on the article that are killing me.)
That's pretty much it, you've got it right. The idea is the following:
Use directives for managing user interface interactions and -some- state changes
Use controllers for managing a shallow set of logic
Use services for sharing data, functionality and business logic.
Aka, just like on your server - try not to load too much into a controller.

Resources