4

Problem description: I'm encountering some problem with laravel escaping quotes when using the laravelcollective/html component. I need the quotes to remain unescaped in order to keep the javascript code working.

Puropose of the code: The user needs to indicate when he wants to keep a form field empty. If they do not, some input is required. I don't want a user to indicate that a field is empty and that he submits some input at the same time. This behaviour is controlled by javascript by removing the checked status of a checkbox when hitting a radio button and vice versa.

There are multiple fields in the form (each with radio buttons and a checkbox if the field should be empty). All have to be checked by javascript before submitting the form. Each field has its own name.

The blade code for a field:

<div>
     {!! Form::checkbox('field_empty',1,null, ['id' => 'field_empty'] !!}
</div>
<div>
     {!! Form::radio('field', 0, null, ['onClick' => 'unselectCheckbox(this,'field_empty')'] !!}
     {!! Form::radio('field', 1, null, ['onClick' => 'unselectCheckbox(this,'field_empty')'] !!}
     {!! Form::radio('field', 2, null, ['onClick' => 'unselectCheckbox(this,'field_empty')'] !!}
</div>

The javascript code:

function unselectCheckbox(box,field)
{
    if (box.value >= 0)
    {
        document.getElementsById(field).checked = false;
    }
}

(I also have a javascript function for removing the checked radio button when clicking the checkbox, but I didn't include it in the code.)

When using the above code, I get a laravel error due to the single quotes around 'field_empty'. Removing the single quotes doesn't result in working js. Using double quotes results in '"' in the generated html.

Of course I could use plain html instead of blade - and so prevent using {!! !!} tags - , but I was wondering whether it's possible to do it in blade, or maybe by using another approach in javascript?


Edit: My form contains multiple items which have to be checked. Each item has its own name, with corresponding checkbox for confirmation of empty value:

<div>
     {!! Form::checkbox('field1_empty', 1, null, ['id' => 'field_empty']) !!}
</div>
<div>
     {!! Form::radio('field1', 0, null) !!}
     {!! Form::radio('field1', 1, null) !!}
     {!! Form::radio('field1', 2, null) !!}
</div>
<div>
     {!! Form::checkbox('field2_empty', 1, null, ['id' => 'field_empty']) !!}
</div>
<div>
     {!! Form::radio('field2', 0, null) !!}
     {!! Form::radio('field2', 1, null) !!}
     {!! Form::radio('field2', 2, null) !!}
</div>
<div>
     {!! Form::checkbox('field3_empty', 1, null, ['id' => 'field_empty']) !!}
</div>
<div>
     {!! Form::radio('field3', 0, null) !!}
     {!! Form::radio('field3', 1, null) !!}
     {!! Form::radio('field3', 2, null) !!}
</div>
Limon Monte
  • 52,539
  • 45
  • 182
  • 213

1 Answers1

4

The attribute value can be escaped by passing it as a HtmlString instance which will not be escaped.

{!! Form::radio('field', 0, null, ['onClick' => new Illuminate\Support\HtmlString("unselectCheckbox(this,'field_empty')")]) !!}

That being said, having onclick events defined inline on the element is generally considered a bad idea. You should instead handle the events on the JavaScript side, so you don't have to include the onClick properties in your element definition. So the HTML should look like this:

<div>
     {!! Form::checkbox('field_empty', 1, null, ['id' => 'field_empty']) !!}
</div>
<div>
     {!! Form::radio('field', 0, null) !!}
     {!! Form::radio('field', 1, null) !!}
     {!! Form::radio('field', 2, null) !!}
</div>

And the JavaScript that handles it should look like this:

(function () {
    var empty  = document.getElementById('field_empty');
    var radios = document.getElementsByName('field');

    // When clicking on any of the radio buttons, uncheck the field_empty checkbox
    for (var i = 0; i < radios.length; i++) {
        radios[i].onclick = function () {
            // The "if (box.value >= 0)" condition is useless here
            // because it will always be true, so I removed it
            empty.checked = false;
        };
    }

    // When clicking on the empty checkbox, uncheck the radio buttons
    empty.onclick = function () {
        for (var i = 0; i < radios.length; i++) {
            radios[i].checked = false;
        }
    };
})();

Here's a working example of the code above. As you can see there's no need for external functions like unselectCheckbox because all the logic is being handled in the event functions.


There is also the jQuery version that is significantly shorter and more readable that the vanilla JS version:

(function () {
    var empty  = $('#field_empty');
    var radios = $('[name=field]');

    radios.click(function () {
        empty.prop('checked', false);
    });

    empty.click(function () {
        radios.prop('checked', false);
    });
})();

And here's a working example of the jQuery version.

Bogdan
  • 43,166
  • 12
  • 128
  • 129
  • Thank you for this answer. However, because I have about 15 different fields of input, I should probably create an array for both variables (empty and field) and loop through these arrays, right? E.g. empty[1], empty[2], ... and the corresponding field[1], field[2],.... Secondly, I'm still looking if it is possible to prevent escaping single quotes in the blade code. – Sébastien Kindt Nov 25 '15 at 19:55
  • I've updated my answer with the solution for using quotes inside the attribute values. If you'd like me to help with your other question about the input fields, you'll have to include your entire form. – Bogdan Nov 25 '15 at 21:00
  • Hi, I tried working with javascript arrays and loop through them to adapt your script, but this didn't work probably because of the way javascript handles arrays. So I edited my post to include more fields of my form. I'll keep searching for how to adapt your script before going back to my original approach with onClick events. – Sébastien Kindt Nov 26 '15 at 12:01
  • I got it working by using functions and calling these in the begininng of the script with the correct variables. – Sébastien Kindt Nov 27 '15 at 21:21