I started with webform module but the built in grid element did not work. Then I tried webform_table_element module, it had some bugs but I managed to configure it. But, unfortunately, it was not able to produce a similar form. I was on a tight deadline (as usual) and did not have time to do something custom, so I decided to try some workaround and after spending a little time I got acceptable result.
I am writing some simple steps to re-generate similar result. I know this is not an ideal solution but it can save a little time if you have to add a couple of similar forms in your Drupal based project.
You need to install webform and webform_table_element module modules first.
a) Add a field of type table_element in webform. table_element type requires you to put key|value pairs in 'Rows' textarea there, convert your 'value' to a simple JSON so it can be accessed later, something like:
1|{"ID":"001", "title":"My Item 1", "rate":"245"} 2|{"ID":"002", "title":"My Item 2", "rate":"460"} 3|{"ID":"003", "title":"My Item 3", "rate":"740"}
And here is a screenshot:
b) Add these child elements under newly created table_element type item:
- Item Name
- Type: markup
- Label: Item Name
- Field Key: item_name
- Value: Name
- Item Rate
- Type: markup
- Label: Item Rate
- Field Key: item_rate
- Value: Rate
- Quantity
- Type: textfield
- Label: Quantity
- Field Key: quantity
- Item Rate
c) We are done with form building here, now time to add some code in template.php file:
// This will display form element in a multi column table function adibf_table_element($variables) { $element = $variables['element']; $header = array(); $header_complete = false; $rows = array(); foreach (element_children($element) as $child) { $child_element = $element[$child]; $rowCustomData = $child_element['#row_title']; $rowCustomData = json_decode($rowCustomData); $row = array($rowCustomData->ID); foreach (element_children($child_element) as $grandchild) { if (!$header_complete && isset($element['#row_titles'])) { if($child_element[$grandchild]['#type'] == 'markup') { $theKey = trim(strip_tags($child_element[$grandchild]['#markup'])); $theTitle = ''; switch($theKey) { case 'Name': $theTitle = t('Item'); break; case 'Rate': $theTitle = t('Rate (usd)'); break; case 'Quantity': $theTitle = t('Quantity'); break; } if($element['#column_titles'][$grandchild] == 'sub-total') $theTitle = t('Sub Total'); $header[] = array('data' => $theTitle, 'class' => $element['#column_titles'][$grandchild]); } else { $header[] = array('data' => t($element['#row_titles'][$grandchild]), 'class' => $element['#column_titles'][$grandchild]); } } if($child_element[$grandchild]['#type'] == 'markup') { if(trim(strip_tags($child_element[$grandchild]['#markup'])) == 'Name') $child_element[$grandchild]['#markup'] = $rowCustomData->title; if(trim(strip_tags($child_element[$grandchild]['#markup'])) == 'Rate') $child_element[$grandchild]['#markup'] = $rowCustomData->rate; if(trim(strip_tags($child_element[$grandchild]['#markup'])) == 'Color') $child_element[$grandchild]['#markup'] = $rowCustomData->color; if(trim(strip_tags($child_element[$grandchild]['#markup'])) == 'Dimension') $child_element[$grandchild]['#markup'] = $rowCustomData->dimension; } $row[] = array('data' => drupal_render($child_element[$grandchild])); } $header_complete = true; $rows[] = $row; } array_unshift($header, array('class' => 'row-title', 'data' => t('Code'))); return theme('table', array('header' => $header, 'rows' => $rows)); } // This will show posted results in multi column table function adibf_webform_submission_render_alter(&$renderable) { if (isset($renderable['#submission'])) { foreach (element_children($renderable) as $key) { $tableRows = array(); if ($renderable[$key]['#webform_component']['type'] == 'table_element') { $cid = $renderable[$key]['#webform_component']['cid']; foreach($renderable['#submission']->data[$cid]['value']['rows'] as $row) { $data = strip_tags($row[0]); $quantity = $row['quantity']; $objData = json_decode($data); $subTotal = $objData->rate * $quantity; $tableRows[] = array($objData->ID, $objData->title, $objData->rate, $quantity, $subTotal); } $tableHeader = array('ID', 'Title', 'Rate', 'Quantity', 'Sub Total'); $theTable = array( 'header' => $tableHeader, 'rows' => $tableRows, ); $renderable[$key]['#markup'] = theme('table', $theTable); } } } }
First code block will display form element visually in a multi column table with one text field for quantity in each row, the second block is for the posted results.
d) The last step is to add a little jQuery somewhere in the theme so after entering quantity, sub total column value would be changed. You can also add a feature to show Net Total somewhere on the page:
jQuery('.webform-component-table_element .form-text').change(function() { var elems = jQuery('.webform-component-table_element .form-text'); var totalAmount = 0; for(var i=0; i<elems.length; i++) { totalAmount += table_element_calculate(elems[i]); } jQuery('#net_total').html(totalAmount); }); function table_element_calculate(elem) { var sPrice = jQuery(elem).parents('td').prev().text(); var hTotal = jQuery(elem).parents('td').next(); var p = 0; try { p = sPrice * jQuery(elem).val(); if(isNaN(p)) p = 0; if(p > 0) hTotal.find('.sub-total').html(p); // alert(p); } catch(e) {} return p; }
Note: I just copied pasted these codes from a project that I did some months ago, so if something don't work please post in comments. Thanks.