Skip to Main Content

Responsive Grid Fields in Expression Engine in Channel Form

An Expression Engine ecommerce project we’re currently working on has required a ‘My Account’ section allowing customers to sign in, manage their previous orders and maintain their personal address book. Using Zoo Visitor has enabled us to take advantage of some additional functionality over the core EE Member Module and allowed us to build a customer area that is completely separate to Expression Engine’s control panel. Nothing particularly new here, but in this case we wanted to allow users to add up to 3 addresses to their profile which in a perfect world, would be approached using either a Matrix or Grid field.

Working outside of the control panel, in theory we had a blank canvas to choose how we laid out our pages and where we put our form elements. However, as Sean Smith recently wrote up his experience of using Channel Form with Grid and Matrix fields, this clearly wasn’t as straight forwards as it should have been. Sean’s article was a great write up of working with Matrix fields, but much as we like Matrix, we wanted to try and achieve this natively with Expression Engine’s Grid field.

Our grid field in the control panel looks like this.

Expression Engine Grid Field

Setting our template up to work with grid required a custom plugin and extension to be written for EE, and while in this example we’ve been setting up our responsive grid within Zoo Visitor update tags, there should be no reason why this approach wouldn’t work for a standard channel form entry.

For those that want to jump straight into an example of what we did, we’ve set up a demo page. For anyone else feeling a little more adventurous, here’s some more detail on what we did.

The first step is to build out the front end template. This is just markup and css, so we can lay out the page with all the responsive goodness we like to build a nice mobile friendly form.

Responsive grid fields in Expression Engine

When it comes to naming your grid form fields however, you’ll need to know the field ID from your channel. The name attributes for our fields looked like this:

field_id_71[rows][row_id_26][col_id_10]

This represents field ID 71 from our exp_channel_data table (which actually refers to a completely separate table - exp_channel_grid_field_71). row_id_26 represents the entry ID a grid line entry, and col_id_10 is the column ID in our grid field, in this case, its our Address 1 field.

We then wrapped our grid row fields within our custom plug-in which you can find in full over on Git Hub.

{exp:grid_row_id table="exp_channel_grid_field_71"
entry_id="{entry_id}"
columns="col_id_10|col_id_11|col_id_12"}

This plugin takes 3 parameters; the grid table in the database, the entry ID of the entry you’re viewing (remember, in our case these are already registered users, so we’re not creating new entries with this example, only editing existing ones), followed by the column names from the Grid database table. It then returns a number of variables for the form we've created, depending on whether we’re editing existing grid data, creating a new row in the grid, or deleting a row.

This variable we now have are:

  • {row_count}
  • {grid_row}
  • {col_id_10_name} + {col_id_10_value}
  • {col_id_11_name} + {col_id_11_value}
  • {col_id_12_name} + {col_id_12_value}
  • {delete}
  • {row_order_name}
  • {row_order_value}

These variables simply output the name attributes we need for our form, but having our plugin create them makes our naming conventions much easier to work with. Instead of having to remember:

name="field_id_71[rows][row_id_26][col_id_10]"

we can simply use:

name="{col_id_10_name}"

Submitting our Zoo Visitor form with just the plugin will correctly update existing row data. However, we wanted to try and mimic the default grid behaviours from the control panel as closely as possible. Adding the ability to delete rows from the grid required an extension which in this case, was using the zoo_visitor_update_end hook. This extension basically grabs the posted data on submit and checks for the latest row order, and whether a line entry should be removed from the grid.

This gave us the core functionality we wanted, but it still fell short of giving us the fancy drag and drop reordering seen in the control panel. Adding some jQuery into our template would give us the bells and whistles we wanted.

First of all we added the functionality for adding new grid rows. A fairly straightforward JQuery function adds the new inputs to the page when the add row button is clicked, and the row number increments by one each time it is clicked. In our example, our grid field is set to a maximum of 3 rows, which is also set in our jQuery.

Next we used jQuery to target our “default” checkboxes so that when one is selected, the others are deselected, allowing a user to specify their preferred address.

Finally the magic drag and drop came from wrapping each grid row in a sortable <div> using jQuery UI. This overwrites a hidden row_order field for each row with the new order. The icing on the cake was to just update the numbers against each row as they were re-positioned.

Arguably for what we needed, the drag and drop reordering is unnecessary, but having come this far, why stop now? Plus, we can see several use cases for this in other ongoing projects, and hopefully others will benefit from being able to use this approach in their projects too.

Limitations with this Example

There are a couple of issues with setting up grid fields in this way and it's clearly not something you can knock together in a few minutes. As every requirement for responsive grid fields will vary, this certainly isn't a one size fits all, but it's given us a solution that allowed us to work outside the control panel with a repsonsive template. In my view, there are 2 particular drawbacks with where we've got to with this so far.

  1. Having updated the order of our grid fields, or added new content, users still need to submit the form for their changes to be committed to the database. With a growing trend of form fields being saved automatically, this would be a nice improvement to the UX here.
  2. The other issue we’ve come across is the question of maximum or minimum rows which are of course options in the grid fieldtype. In our case, we weren’t too concerned about all the grid rows being removed, but we did want to set a maximum number of rows, which we did in the jQuery. We’ve basically got some jQuery script for each allowable row in the grid, so if you needed to add an unlimited number of rows, this would likely require some refactoring of the code to allow this. However, I suspect in most cases where channel form is being used, there will want to be some limits applied to the data that users can submit anyway, so perhaps not such a major issue.

Rounding Up

Hopefully this is a useful primer on setting up responsive grid fields in Expression Engine. This really opens up opportunities to have your visitors submit information directly into your EE database using native and responsive functionality without having to sacrifice the flexibility offered by the grid fieldtype.

We’ve created a live example (well almost; minus the live data and actual submission into EE) rather than posting all the code here, so check it out for yourself. Feel free to poke around the template and use the code as a basis for your own experiments. The plug-in and extension can be found in the same repo over on Git Hub.

Andrew profile

Andrew is the founder of multi-award winning A Digital and believes that technology should be an enabler, making a positive impact on the way people live and work.

Learn more about us: