1
votes

I'm using Phalcon to generate a form and for some html structure and responsive reasons i need to cut my form generation in two parts, a "desktop" part and a "mobile part" using bootstrap responsive class

{{ form(form.getAction(), 'method': 'post', 'role': 'form','id' : 'criteres','class' : 'row center-block fond_partie not_middle_lg','style' : 'max-width : 1064px', 'action' : '/propal/recherche') }}
    <div class="row hidden-sm hidden-md visible-lg hidden-xs" id="large">
    {% for element in form %}
            <?php if (is_a($element, 'Forms\Element\Datepicker')) { ?>
                {{ element }}
            <?php } else if (is_a($element, '\Phalcon\Forms\Element\Radio')) { ?>
            <div class="form-group col-xs-12 ">
                <?php if ($element->getAttribute('titre')) { ?>
                    <label class="bold">{{ element.getAttribute('titre') }}</label>
                <?php } ?>
                <div class="form-check">
                    <label><input type="radio" class="form-check-input" value="{{ element.getAttribute('value') }}" name="{{ element.getAttribute('name') }}">{{ element.getName() }}</label>
                </div>
            </div>
            <?php } else if (is_a($element, '\Phalcon\Forms\Element\Check')) { ?>
                <?php if ($element->getAttribute('titre')) { ?>
                    <div class="form-group col-md-12 col-lg-12 col-xs-6">
                <?php } else { ?>
                    <div class="form-group col-md-12 col-lg-12 col-xs-6">
                <?php } ?>
                <?php if ($element->getAttribute('titre')) { ?>
                    <label class="bold" >{{ element.getAttribute('titre') }}</label><br>
                <?php } ?>
                    {{ element.render() }}
                    {{ element.label(['class': 'control-label']) }}
                </div>

            <?php } else { ?>
            <div class="form-group col-xs-3 col-lg-12">

                {{ element.label(['class': 'control-label bold']) }}
                {{ element.render(['class': 'form-control']) }}
            </div>
            <?php } ?>
    {% endfor %}
    </div>


    <div class="row visible-xs visible-sm visible-md hidden-lg" style="margin-bottom: 45px" id="small">
    {% for element in form %}
            {% if loop.index == 1 %}
            <div class="col-xs-3">
                <div class="row">
                    <div class="col-xs-12" style="margin-bottom: 10px">
                    {{ element.label(['class': 'control-label bold']) }}
                    {{ element.render(['class': 'form-control']) }} 
                    </div>
            {% elseif loop.index == 2 %}
                        {{ element }}
            {% elseif loop.index == 3 %}
                    <div class="col-xs-12" style="margin-top: 10px">
                        {{ element.label(['class': 'control-label bold']) }}
                        {{ element.render(['class': 'form-control']) }}
                    </div>
            {% elseif loop.index == 4 %}
                    <div class="col-xs-12" style="margin-top: 10px">
                        {{ element.label(['class': 'control-label bold']) }}
                        {{ element.render(['class': 'form-control']) }}
                    </div>
                </div>
            </div>
            {% elseif loop.index == 5 %}
            <div class="col-xs-3">
                <div class="row">
                    <div class="col-xs-12">
                    {{ element.label(['class': 'control-label bold']) }}
                    {{ element.render(['class': 'form-control']) }} 
                    </div>            
            {% elseif loop.index == 6 %}
                    <div class="col-xs-12" style="margin-top: 10px">
                        {{ element.label(['class': 'control-label bold']) }}
                        {{ element.render(['class': 'form-control']) }}
                    </div>            
            {% elseif loop.index == 7 %}
                    <div class="col-xs-12" style="margin-top: 10px">
                        {{ element.label(['class': 'control-label bold']) }}
                        {{ element.render(['class': 'form-control']) }}
                    </div>
                </div>
            </div>
            {% elseif loop.index == 8 %}
            <div class="col-xs-3">
                <div class="row">
                    <div class="col-xs-12">
                        <?php if ($element->getAttribute('titre')) { ?>
                            <label class="bold">{{ element.getAttribute('titre') }}</label>
                        <?php } ?>
                        <div class="form-check" style="margin: 10px 0">
                            <label><input type="radio" class="form-check-input" value="{{ element.getAttribute('value') }}" name="{{ element.getAttribute('name') }}">{{ element.getName() }}</label>
                        </div>
                    </div>            
            {% elseif loop.index == 9 %}
                    <div class="col-xs-12" style="margin: 10px 0">
                        <label><input type="radio" class="form-check-input" value="{{ element.getAttribute('value') }}" name="{{ element.getAttribute('name') }}">{{ element.getName() }}</label>                        
                    </div>            
            {% elseif loop.index == 10 %}
                    <div class="col-xs-12" style="margin: 10px 0">
                        <label><input type="radio" class="form-check-input" value="{{ element.getAttribute('value') }}" name="{{ element.getAttribute('name') }}">{{ element.getName() }}</label>                        
                    </div>  
                </div>
            </div>
            {% elseif loop.index == 11 %}
              <div class="col-xs-3">
                <div class="row">
                    <div class="col-xs-12">
                    <?php if ($element->getAttribute('titre')) { ?>
                        <label class="bold" >{{ element.getAttribute('titre') }}</label><br>
                    <?php } ?>
                        {{ element.render() }}
                        {{ element.label(['class': 'control-label']) }}
                    </div>
            {% elseif loop.index > 10 %}
                    <div class="col-xs-12">
                        {{ element.render() }}
                        {{ element.label(['class': 'control-label']) }}
                    </div>
            {% endif %}

    {% endfor %}
            </div>
        </div>
    </div>
    <i class="fa fa-caret-right" aria-hidden="true"></i>
    {{ submit_button("Lancer la recherche", "class": "btn btn-research") }}
{{ end_form() }}

The problem is when i try to send my form, there is some problems with duplication of names and ids so i tried something with javascript

if ($(window).width() >= 1183) {
    console.log("more");
    $("#small  :input").attr('disabled', 'disabled'); //Disable
    $("#large  :input").removeAttr('disabled'); //Enable
    // the width of browser is more then 1200px
} else {
    console.log("less");
    $("#small  :input").removeAttr('disabled'); //Disable
    $("#large  :input").attr('disabled', 'disabled'); //Enable
    // the width of browser is less then 1200px
}

But there are still problems with datepicker, checkbox or radio buttons.

So i see two differents solutions:

First: have only one generation of the form, but in desktop and mobile the structure of the form is totally different so it's very difficult but maybe there is some html/css tricks that I don't know ?

Second: Change the names and the ids of all the mobile input but in my controller i have to duplicate my "getPost functions"

Do you have any advice?

2

2 Answers

1
votes

My opinion is that having duplicate content for desktop/mobile is a bad idea. Few reasons:

  • accessibility;
  • code is bloated;
  • you make your life harder as you noticed yourself :)
  • SEO...

What you should aim at? Having only 1 of each inputs and no need for JavaScript except for client side validation and ajax sending :) Handle all responsive stuff in the CSS media queries and maybe a very little JavaScript if you really really need to move something accross the screen.

I usually have a config class for every form that extends a base form class. In that config file I'm setting validation rules and other element specific options. A quick example:

class ProfileRegistration extends BaseForm
{
    private $_fields = [
        'names' => [
            'type' => 'text',
            'validation' => 'required',
            'width' => '...'
        ],
        'email' => [
            'type' => 'email',
            'validation' => 'required',
            'width' => '...'
        ],
        'password' => [
            'type' => 'password',
            'validation' => 'required|min[5]'
            'width' => '...'
        ],
        'newsletter' => [
            'type' => 'checkbox',
            'width' => '...'
        ],
        'agree' => [
            'type' => 'checkbox',
            'validation' => 'required',
            'attributes' => [
                'value' => 'default value'
            ]
        ],
        'recaptcha' => [
            'type' => 'recaptcha'
        ],
    ];

Again, please note that this is my personal 'addition' to Phalcon's form (it is not built-in).

For your form it should look something like this:

{% for element in form %}
<div class="form-group {{ element.width|default('col-md-12 col-lg-12 col-xs-6') }}">
    {{ element.label(...) }}
    {{ element.render(...) }}
    {{ element.messages(...) }}
</div>   
{% endfor %}
0
votes

Ok i find a solution, i will just use the mobile one, it works well and the structure is very similar