CrtlAltDylan's avatar

Is there a JS library/plugin specifically for dynamic forms?

Blade is great. It makes reading and writing static forms a cinch. However when it comes to dynamic forms there's not a clear answer. I've been using jQuery functions to add/delete/modify fields based on user events. However this is resulting in a lot of copy pasta which is not yummy and I feel like this is a common enough problem there is a JS library out there specifically for forms.

Is this out of scope for Blade? Is this what frontend JS frameworks attempt to answer?

0 likes
8 replies
austenc's avatar

I'd like to know of a nice way to handle this as well... usually I resort to making a partial view and then rendering the on-page fields with that, and using that for a 'clone' element that I can use jquery to clone / insert into the DOM. My approach works, but isn't exactly ideal considering it feels like you have to 'do it manually' each time.

bashy's avatar

Define dynamic form? Depending on what you want to do, you could write some macros

Form::macro('fooField', function()
{
 return '<input type="custom"/>';
});
Form::fooField();

Or something similar, I'm not sure on the scope of what you want to do to form elements.

1 like
CrtlAltDylan's avatar

@bashy that's definitely helpful. There are 3 main use cases that I run into over and over:

1) A form as a type of field that can be added 0, 1, or many times (your typical 'add expense' or 'add contact' field)

2) A field that shows/hides based on certain conditions (like a checkbox causing another part of the form to show)

3) A search bar in the form that makes an AJAX call to a local API endpoint that provides results to the form for a user to selection. That selection is used on the form.

To add to the complexity, many of these forms are on modals. Modals are also a great UX tool, but if you iterate over a collection in your view then you have to generate a corresponding modal with each instance.

Something like this:

<a data-target="sample-modal{{$object->id}}">Edit this object</a>



 <modal id="sample-modal{{$object->id}}>
     ...
 </modal>

I think I could leverage some macros to do this but I'm starting to understand why people are using Laravel as a RESTful API for frontend JS when your pages are very user event driven.

nolros's avatar

@CrtlAltDylan have you looked at AngularJS or ReactJS? Example, ng-repeat in Angular would give you the iteration, you also have a number of JS state options. You can get Blade and these to work together, but it does take work.

Example, I use both Blade and AngularJS for my average my filed. PS, I don't claim to be an AJS expert and I guess most AJS developers would frown at how I use it ... lol.

I add a class based whether showRequiredFields based in boolean state. In my Angular Controller.

ng-class="{'showRequiredFieldClass' : showRequiredFields }">

I use AJS objects to maintain state for me on entry or exit of fields. You can do anything like, add classes, show, hide, AJAX calls etc, based on state or you call directly.

 'ng-focus' => 'state.username=true',
 'ng-blur' => 'state.username=false',

// I use ng-cloak and no-show to hide or show DOM elements based on vars.

<span ng-cloak class="ng-cloak">Your nickname or username is your MatrixMe public identity online. </span>
                <div class="form-group">
                    <i class="fa fa-user fa-2x fa-fw"></i>
                    <div class="field-inner" ng-class="{'showRequiredFieldClass' : showRequiredFields }">
                        {!! Form::label('text', 'MatrixMe Username:', ['class' => 'Required']) !!}
                        <span class="fa fa-question-circle fa-lg fa-fw" ng-click="fieldHelp(0)"></span>
                             {!! Form::text('username', null ,[
                                 'class' => 'form-control',
                                 'ng-class' => "{'fieldIsFocusClass' : state.username }",
                                 'ng-model' => 'user.username',
                                 'ng-focus' => 'state.username=true',
                                 'ng-blur' => 'state.username=false',
                                 'placeholder' => $placeholder['username'],
                                 'tabindex' => "1",
                                 'autofocus'
                                 ])
                             !!}

                    </div>
                    <div class="fieldMessages">
                        @include('forms.partials.fielderrors', array('fieldtype' => 'username'))
                         <div class="field-help" ng-show="showFieldHelp && fieldNumber == 0">
                             <span ng-cloak class="ng-cloak">Your nickname or username is your MatrixMe public identity online. </span>
                         </div> <!-- div - field-help -->
                    </div>
                </div>

Iteration using Angular

 <li ng-repeat="orders in order">
    <a ng-if="availableStock(stock.inStock)" // regular href and HTML stuff</a>
 </li>

You also have custom directives. Simple example but to keep two columns in my form equal in height I have the following directive:

 <div id="rightColumn" mirror-reflect="leftColumn">

which then calls this directive in Angular. You can create a directive to be anything in a DOM, attar, value, etc.

myApp.directive('mirror', function () {
    return {
        restrict: 'A',
        link: function (scope, elem, attr) {
            scope.$watch(function () {
                angular.element(document.getElementById(attr.mirrorReflect)).height(elem.height()-95);
            });
        }
    };
});
1 like
bashy's avatar

I would definitely look into the above, for what you want to do, it's great. Macros can do some of it but still going to be messy

1 like
CrtlAltDylan's avatar

@nolros

Exactly what I was asking. I'm not a frontend minded person, but I can see that normal Blade + jQuery is functional but it's just not as scalable as I thought. I'm definitely going to build a RESTful API that both the web and mobile sides of the application.

So many advantages:

1) complete separation of view from the application

2) Don't have to duplicate code for mobile or web, the API expects JSON endpoints as GETers and POSTers.

3) Use a tool that has a separate goal than that of Laravel, but you can still leverage it for your application.

Please or to participate in this conversation.