Passing conditional disabled attribute to blade component with ternary operator - laravel

Is there a way to conditionally pass a disabled attribute to a blade component? For example this question and answer mention how to use the ternary operator to pass in the value of the attribute but the attribute name will be there regardless.
I am specifically trying to use the ternary operator in the blade component tag to add (or not add) the disabled attribute
template code:
<x-button {{!$aircraftType->canIslandBuild($island) ? 'disabled' : ''}}>
Build
</x-button>
button component code:
<button {{ $attributes->merge(['class' => 'inline-flex']) }}>
{{ $slot }}
</button>
The error involves adding {{!$aircraftType->canIslandBuild($island) ? 'disabled' : ''}} to the x-button tag.
The error that I'm getting is: syntax error, unexpected token "endif", expecting end of file
Also if I change this {{!$aircraftType->canIslandBuild($island) ? 'disabled' : ''}} to {{''}} the same error happens so I'm curious if you can render strings from php code inside of the component tag header like you can anywhere else in a blade template. I know there are other ways to pass in data and conditionally add the disabled attribute by modifying the button component code but I would like to know if there is an easy solution here.

Went with matiaslauriti's comment and decided to replace
{{!$aircraftType->canIslandBuild($island) ? 'disabled' : ''}}
with
:disabled="!$aircraftType->canIslandBuild($island)"
without changing anything else. It seems disabled="disabled" is included in the $attributes variable only when the value is true. This means that the button renders a disabled="disabled" only when !$aircraftType->canIslandBuild($island) is true and when it is false, no disabled is rendered on the final html for the button.

Related

Why does this Blade component not receive a parameter?

I am using Laravel 9 and trying to understand the components.
I have this 'anonymous' component (extract) :
<option value="{{ $phase->id }}" #if(isset($phase_id) && $phase_id===$phase->id) selected #endif>
{{ $phase->name }}
</option>
The component is called like that :
<x-select-phase id="phase_id" name="phase_id" :phase_id="$event->phase_id"
I am expecting that the var $phase_id exists inside the component. It is not the case, and do not understand why. I tried a lot of things without success. What can I try next?
https://laravel.com/docs/9.x/blade#casing
Component constructor arguments should be specified using camelCase, while kebab-case should be used when referencing the argument names in your HTML attributes.
This means:
:phase-id="$event->phase_id"
should generate a variable:
$phaseId

#if condition in input field for toggle checkbox - Laravel

My blade template contains a form where data can be inserted like name, mail, etc.
One input field is a toggle checkbox where you can check whether you are an intern or not.
Intern => toggle checked and "Yes" is visible (equals in database 1)
Not intern => toggle is not checked and "No" is visible (equals in database 0)
The checking of the box is working but the status intern or extern isn't sent to the database. Bellow, you will find my code. I don't know if this is the correct way to this.
<input checked data-toggle="toggle" data-on="Yes" {{$person->intern_extern == '1' ? 'checked' : ''}}
data-off="No" {{$person->intern_extern == '0' ? 'checked' : ''}} data-onstyle="primary"
data-offstyle="info" type="checkbox"
name="intern_extern">
As discuss with #N69S , I will suggest you a solution that will require less code.
Your yes/no on the client-side equal 1/0 on server-side.
By default, checkbox into form is not send to server-side if it's not checked.
So, using how request work within Laravel, you can create a checkbox like this one:
<input name="intern_extern" type="checkbox" {{$person->intern_extern == 0 ? 'checked' : ''}}>
Into your controller, when updating a person model, do this:
$person->intern_extern = $request->input('intern_extern', 0);
This is what N69S explain about the $request->input():
yes, by default it is null but you can set it like that when you recover the input trait InteractsWithInput # public function input($key = null, $default = null)
In this case, if the checkbox inter_person is checked, the form will post the input with the value true. If not checked, it will not be send and the value will be 0.
In case you are using this to create your model: $model = Model::create($request->all());, you will have to set the default value into your migration $table->boolean('intern_extern')->default(0); to make all this work.
EDIT - Simple suggestion
When I use boolean, I like to name them like "isSomething". In your case, isIntern or isExtern. So when you have to refer to it, it's simple to read it. isIntern (yes or no) or isExtern (yes/no).
Try it.
<input data-toggle="toggle" data-on="Yes" data-off="No" #if(!empty($person) && $person->intern_extern) {{ 'checked' }} #endif data-onstyle="primary" data-offstyle="info" type="checkbox" name="intern_extern">
here #if(!empty($person) && $person->intern_extern) it'll check $person->intern_extern == 1;
You need to have value="Yes" for this to work which is currently absent from your code.
<input
name="intern_extern"
type="checkbox"
value="Yes"
{{ $person->intern_extern == '1' ? 'checked' : '' }}
data-toggle="toggle"
data-on="Yes"
data-off="No" {{$person->intern_extern == '0' ? 'checked' : ''}} data-onstyle="primary"
data-offstyle="info"
>
BUT, if my memory serves me correctly, you cannot have a "No" value sent to the backend when submitting the form unless you're using some JS to handle this.
Why? Because checkboxes can only really represent one value, in your example if it's checked it will show up as intern_extern = Yes in the request, however, if the checkbox is unchecked it will be absent from the request.
Considering this you may want to switch to a different form control: <select> for example to represent Yes/No. Or continue using the checkbox but just handle it appropriately in PHP code, i.e. if it's not in the request then fill out the DB with No/0
A checkbox input is not sent with the form submission if not checked. You can counter it like this:
<input type="hidden" name="intern_extern" value="0"/>
<input checked data-toggle="toggle" data-on="Yes" #if(isset($person->intern_extern) && $person->intern_extern)checked="checked"#endif
data-onstyle="primary" data-offstyle="info" type="checkbox" value="1" name="intern_extern">
if the checkbox is checked, it will override the hidden input value since it has the same name

Correct approach for rendering optional param in blade

I noticed that below construction is not correct for Blade
<div class="constant #if($some_condition)optional#endif">
cause this is converted to in PHP which is invalide
<div class="constant <?php if($some_condition): ?>optional<?php endif; ?>">
To make this statement work I need to put close tag on different line but it looks very bad, especially if there are many others attribute.
<div class="constant #if($some_condition)optional
#endif" data-id="1" tabindex="2" data-etc="...">
What is the right way of rendering such kind of conditions in Blade?
Try the short version of if statement.
$some_condition ? 'optional' : ''
Using the code above, if the condition is true it will return the the string 'optional', if the condition is not true it will return an empty string I mean this ''. Note, an empty string as attribute do nothing inside Html element.
In your case it should look like this:
<div class="constant {{ $some_condition ? 'optional' : '' }}">

How to style successful input fields in Thymeleaf

I would like to use Bootstrap's has-success and has-failure classes with Thymeleaf.
So far I have
<div th:class="${#fields.hasErrors('field')}? 'form-group has-error' : 'form-group'"></div>
This displays the failure style correctly, when the form is posted and the field is invalid.
However if I change the second part of the ternary to 'form-group has-success', then on the initial form GET request, then, of course, it styles it as a success, even though the form hasn't been posted yet.
My question: is there a way in Thymeleaf to handle the following
Displays a form without any styling on GET.
On POST apply has-error or has-success classes.
I think you'll need to add attributes to your Model in the back-end for this.
In you GET request, change nothing. In your POST request, add an attribute: ["hasErrors", true] if the form data you send via the post is incorrect, false otherwise.
Now in your html you can add the following:
<th:block th:if="${hasErrors != null}">
<div th:class="${hasErrors ? 'form-group has-error' : 'form-group has success'"></div>
</th:block>
<th:block th:unless="${hasErrors != null}">
<div class="form-group"></div>
</th:block>
You check if the hasErrors model attribute isn't null, if it is, it means you're in the GET method and you should display a simple form-group. If the hasErrors is not null, you can create the ternary expression based on the boolean value hasErrors. The th:block is non-html. You can replace it with a div, but then you neen an extra div just to check a boolean.
I'm not going into GET/POST problem but I think that this can help you:
New th:errorclass for adding CSS class to form fields in error
Until now, whenever we wanted to apply a specific CSS class to an input field in a form when there were errors for that field, we needed to use the th:class or th:classappend attributes.
In Thymeleaf 2.1, in order to simplify this structure, a new th:errorclass attribute processor has been introduced. This processor will read the name of the field from the name or th:field attribute in the same tag, and apply the specified class if such field has errors.
Note the 'error' literal is in fact a token, so no single quotes are really needed.
The result is much more concise. Note also that th:errorclass works like th:classappend, not th:class. So the specified class will in fact be appended to any existing ones.
http://www.thymeleaf.org/whatsnew21.html#errcl
I found that Thymeleaf as a hasAnyErrors function.
<div class="form-group row"
th:attrappend="class=${#fields.hasAnyErrors()
? #fields.hasErrors('field') ? ' has-error' : ' has-success'
: '' }">
This now works.
When the user GETs the form, hasAnyErrors is false, so the empty string is appended and the input and label receive the default style.
When the user POSTs the form, if there are any errors then the first part of the ternary is evaluated. This adds the has-error or has-success styles.
This was inspired by Roel Strolenberg's answer below.

Laravel input checkbox if selected on edit

I have an array that I am setting up as checkboxes
<?php $buslist = array('Brooklyn','Lakewood'); ?>
#foreach ($buslist as $buses)
{{Form::label('brooklyn_1',$buses)}}
{{Form::checkbox('BusList2[]', $buses,false, ['id'=> $buses]) }}
#endforeach
Then I switch it to an string with a , using implode
But when I try to edit my information, none of the checkboxes are selected and the information gets lost on update.
What code can i put into the blade checkboxes, if that bus is in my string list?
Checkboxes are finicky creatures. In your form you actually have to do something like this
{!! Form::hidden('new-group-user-member', 0) !!}
{!! Form::checkbox('new-group-user-member', true, NULL) !!} Member
When a checkbox is not checked nothing gets sent to the server so you never know when to change the value in the backend. If you add a hidden form field with the same name and a value of 0 it will get sent with the form even though the checkbox is not checked.
In third parameter use in_array($buses, $buslist) instead of false. Your blade code will look like this:
{{Form::checkbox('BusList2[]', $buses,in_array($buses, $buslist), ['id'=> $buses]) }}

Resources