using checkboxes in Laravel's Form::model - mysql

I'm having trouble with Laravel's Form::model() construct. I was able to populate it with my model data but the checkboxes aren't being checked. The values are being set to 1 or 0 (courtesy of Eloquent calling a "boolean" a "tinyint" in MySQL), but I can't see how to use the Form::model() approach and set that checked attribute if the value coming is an integer and not a boolean (hence why I think Form Model Binding for checkboxes isn't working).
I'm specifying this in my view:
{{ Form::checkbox('hasDiscount') }}
And the form builder is returning this:
<input name="hasDiscount" type="checkbox" value="1" id="hasDiscount">

I think it's not really related to data-value. The value could be 'true' and the checked attribute could be false as well.
If you want to display checkbox with checked attribute, you can try my wait (it's not the best, I admit):
Form::model($model)
Form::checkbox('name', null, $model->value)
Form::close()
The third parameter could be convert to false if the value of model is null or 0 and the checkbox is not checked. otherwise, it's checked.
If you have another idea, please share it.

Related

Thymeleaf dynamic list setter

I would like to simplify some code of mine. It's quite simple honestly. I have 1 input field, and if a certain condition is fulfilled, it should have 1 more attribute. It should have the list attribute. The Problem I'm having is, that I don't know how to dynamically set an attribute.
The code looks like this currently:
<input th:if="${fieldIndex == 0 && !#arrays.contains(dropDownFields, y)}"
th:disabled="${#arrays.contains(disabledFields, y)}"
th:field="*{ZMatrixValues[__${dataIndex}__].tableValues[__${i}__][__${y}__]}"
class="table-input" type="text" onfocus="focused(this)">
<input th:if="${fieldIndex == 0 && #arrays.contains(dropDownFields, y)}"
list="list"
th:disabled="${#arrays.contains(disabledFields, y)}"
th:field="*{ZMatrixValues[__${dataIndex}__].tableValues[__${i}__][__${y}__]}"
class="table-input" type="text" onfocus="focused(this)">
And as you can see, the 2 input fields are the exact same, except when this condition is true: #arrays.contains(dropDownFields, y), then it should also add the attribute list="list". Is there any easier way than copying so much code?
Any help would be appreciated, thank you!
Instead of using th:if you can use th:attr and place the conditional logic in that attribute using the Thymeleaf "if-then-else" operator: (if) ? (then) : (else).
Here is a simplified version of your code showing this:
<input th:attr="list=${#arrays.contains(dropDownFields, y) ? 'some_value' : null}">
If the #arrays.contains condition is true, then the list attribute will be added to the <input> element; otherwise if the condition is false, and the null is returned, then no attribute will be added.
Instead of 'some_value' you can use whatever you want - including the th:field expression from your question.
All the other attributes in your question can be included in the tag, and will be unaffected, since they are not part of the (if) ? (then) : (else) logic.

What is the correct and most safe way to check if HTML form checkboxes and such have been POST-set?

This has confused me since the early days. Maybe it's just in my head, but it seems to me as if this has varied over time, between browsers, and possibly even depending on the local language/locale.
Basically, whenever I need to check if a HTML input of type "radio" or "checkbox" has been set, I always do:
if (isset($_POST['the_name']) && trim($_POST['the_name']))
// do stuff
This just makes sure that the POST variable is sent whatsoever (which in itself doesn't mean that it was actually checked/selected, as far as I can tell, since its "value" can be an empty string) and that it's something other than '' (empty string). It seems like this has worked for a long time, but I have two problems with it:
It's ugly. I need to abstract it into a function, but then I want to know if it's a good idea in the first place, or wrong somehow.
It makes the assumption that any non-empty string value means "checked" or "selected", whereas the standard may say a specific string value such as "on", or maybe any number of such strings depending on the language/locale.
Are there cases where my above code falls apart? Do browsers ever submit POST forms where they include names which have no user input/selection in the HTTP request? Or does the existence of a name in the POST blob mean that that "field" has been actively changed/set/checked/selected?
The idea behind checkboxes is that the value is sent over to the server only if the checkbox was checked when submitting the form. The value can be anything, even an empty string. As long as the field is part of the transmitted form it means the box was ticked.
The value attribute is one which all <input>s share; however, it serves a special purpose for inputs of type checkbox: when a form is submitted, only checkboxes which are currently checked are submitted to the server, and the reported value is the value of the value attribute. If the value is not otherwise specified, it is the string on by default.
This means you could have a form like this:
<form action="" method="get">
<input type="checkbox" name="c1" value="">
<input type="submit" value="Send">
</form>
If the checkbox is not checked when submitting then $_GET will be an empty array.
If the checkbox is checked then the value of $_GET will be:
array('c1' => '');
To check whether the box was ticked when sending the form you only need isset()
if (isset($_POST['c1']) {
// The box was checked!
}
Sometimes you would like to assign a value attribute to your checkbox. In such situations you can use the shorthand operator for isset() function ??.
// Create a variable from the checkbox value or assign an empty string if the box was not checked
$nyCheckbox = $_POST['c1'] ?? '';

UI-Select default placeholder than can change

So I would like to set my placeholder to have a default value which I originally had, but I have a modal view which when I create a user it updates which is done due to the following code:
<ui-select-match class="ui-select-match" placeholder="Test">{{$select.selected.loginName}} </ui-select-match>
However I would like to have a value beforehand, such as please select an option, etc. I tried using:
attrs.$set('placeholder', userEntity.loginName)
But atlas, no success. I was wondering has anyone had this issue before and if so, is it possible to have a default placeholder which can then be changed?
You should use ng-attr-placeholder to bind the attribute value to an angularJS expression, validate if the value you want to use is there otherwise return a fallback string {{ placeHolderMsg ? placeHolderMsg : 'Default placeholder'}}
e.g.
<ui-select-match
class="ui-select-match"
ng-attr-placeholder="{{ $ctrl.userEntity.loginName ?
userEntity.loginName : 'Please select an option'}}">
{{$select.selected.loginName}}
</ui-select-match>

How does MVC decide which value to bind when there are multiple inputs with the same name?

I have an edit page where several fields are conditionally disabled, based on the user's role. When the fields are disabled, their values are not posted to the server (as expected), which causes the ModelState to be invalid, as the values are required.
To get around this, I want to add Html.HiddenFor() for the fields; so that a value will still get posted (and so that it will retain those values if the View is returned). However, in the case that those fields are not disabled, I will then have both a TextBoxFor and a HiddenFor going to the same model property.
I have run a couple tests, and it appears that when this happens, the value of the first element on the form will be binded to the model, while the next one just gets ignored. If this is the case, then I should be able to just put the HiddenFor after the TextBoxFor, in which case the value of the hidden input will only be posted when the regular input is disabled.
#Html.TextBoxFor(m => m.FirstName)
#Html.HiddenFor(m => m.FirstName) #*Only gets binded to the model if the above text box is disabled*#
(There is some JavaScript that conditionally disabled the visible TextBox).
So two questions: 1) Is it documented that MVC binding will always work this way; can I safely have both of these fields?
And, 2) Is there a better approach to accomplishing this? I know that I can but the HiddenFor inside an #If statement so that it will only get created if the TextBox is disabled; but that is a lot of extra logic in the View that I'd like to avoid.
The DefaultModelBinder reads the values from the request in order and binds the first matching name/value pair and ignores subsequent matches (unless the property is IEnumerable). This is how the CheckBoxFor() method ensures a true or false value is always submitted to the controller (the method generates a checkbox with value="True" and a hidden input with value="False"), so you can safely add the hidden input after the textbox.
One option you might consider rather than a disabled textbox, is to make it readonly, which means it will always submit a value, therefore you only need one input (and you can always style it to look disabled if that is what you want).

Not able to set value of hidden field using viewbag when value is type of bool.

Controller side i have
ViewBag.CanAddNewStudent = Convert.ToBoolean(Request.Cookies["SignInOption"]["Can Add New Student"].Split(',')[0]);
And at the view side i take Hidden field as
<input type="hidden" id="HiddenCanAddNewStudent" value="#ViewBag.CanAddNewStudent">
<label>#ViewBag.CanAddNewStudent</label>
Here in Hidden field i get Value="value" instead of Boolean value.
This is an unfortunate side effect of a feature introduced in Razor V2 called conditional attributes. If the value of the property is a bool it will repeat the attribute and is designed for use in attributes such as checked or disabled where you can use a bool value and if the value is true it will generate checked="checked" or disabled="disabled", but if the value is false then the attribute will be omitted.
You can read more about this feature in Cleaner Conditional HTML Attributes In Razor Web Pages and Applying Conditional Attributes in ASP.NET MVC Views
To generate the hidden input, you can use
#Html.Hidden("HiddenCanAddNewStudent", ViewBag.CanAddNewStudent)
which will also include a name="HiddenCanAddNewStudent" attribute in addition to the id="HiddenCanAddNewStudent" attribute. However, the MVC way to handle this is to use a view model that includes a property for your bool
public bool CanAddNewStudent { get; set; }
and set the value of that property before you pass the model to the view, then in the view
#Html.HiddenFor(m => m.CanAddNewStudent)
It is how boolean values usually work in HTML (for example, in checkboxes) -- the logical value is represented not by the value of attribute value, but by its presence (if the tag has this attribute, the value is true, otherwise false). It is really strange that this logic is applied to hidden fields, but probably the framework works this way.
Anyway, I would recommend to convert the boolean value into a string and assign this string to the field. By their nature, values of hidden fields are strings, not booleans.
At top of View take boolean variable and save viewbag value in it and then pass that variable to your hiddenfield.
#{
bool _canAddNewStudent=Convert.ToBoolean(Viewbag.CanAddNewStudent);
}
<input type="hidden" id="HiddenCanAddNewStudent" value="#_canAddNewStudent">
View(html)
<label id="HiddenCanAddNewStudent" style="display:none;">#ViewBag.CanAddNewStudent</label>
jQuery
$('#HiddenCanAddNewStudent').text(); //value of ViewBag.CanAddNewStudent
Try this, if you want to use input tag
<input type="hidden" id="HiddenCanAddNewStudent" value=#Convert.ToString(ViewBag.CanAddNewStudent)>
this will return true in jQuery and also show in HTML value ="True"