Dynamically assign values in repeat groups

Just to followup on the idea of doing this with javascript.
Assuming 'access_control_learners___dbj_elementname' is the name of the dbj element in the parent form at the top
...And you have created a field element named 'apprenant' in the repeat group table ('form_group_repeat') to hold the Apprenant names.

This javascript code could be used to populate the added apprenant fields with the labels from the dbj element.

JavaScript:
    jQuery("select#access_control_learners___dbj_elementname option").each( function() {
        var optTxt = jQuery(this).text();
        setTimeout(
            function()
            {
               jQuery("input[id^='form_group_repeat___apprenant_']").each( function() {
                    if(jQuery(this).val() == ""){
                        jQuery(this).val(optTxt);
                        jQuery(this).attr('readonly','readonly');
                        return false;
                    } else {
                        jQuery(this).attr('readonly','readonly');
                    } 
                });
        }, 2000);             
    });

Setting the input to readonly will prevent the user from changing it, but still allow it to be submitted/saved with the form.
You can use the template css style sheet to add some css to that input so it doesn't look like a readonly/disabled input element.

I'm not sure how all that Fabrik magic works per the group setting. This code seems to work fine when adding new repeats. But what would happen if the R?p?tition value is reduced - i.e. there is less Apprenant names than the last time the record was edited? You'd have a whole new can of worms there - as you'd have to identify the repeat that needs to be deleted. But I suppose that would be easy enough to do if you just created an array of names used in the dbj and compared it to the array of names used in the repeats. I don't know if that could all be done just with javascript alone or you would have to write a 'user ajax' function to handle it.
 
Last edited:
Thank you very much Bauer!!! It works like a charm! the '.each( function() {' solve my problem! You're a genius!
 
Glad that you managed to achieve it.

As an alternative, you could probably attach a standard javascript onload event to the dropdown field to set it to readonly without any coding.
 
Thank you very much Bauer!!! It works like a charm! the '.each( function() {' solve my problem! You're a genius!
Well I wouldn't go that far - but I do enjoy coming up with 'creative' solutions. So, no problem; Glad I could help.:)
 
This code works great!

But could I alter this code to display the 'label' in the label of the element and the id value in the field?

Perhaps by using a database join element in the repeat group.

I would like to populate a set of repeat groups with a description for the user to view and an id to store in the database when the user selects which should be stored with a radio button.
 
Last edited:
I have spent endless hours trying to re work this code to achieve this.

Using .val() I can get the value of the parent DBJ, but I can't preselect my DBJ in my repeat group.
 
If you want to post your code, I'll take a look.

Remember to use the "Insert" button in the editor to insert your code, so it preserves formatting.

-- hugh
 
Thanks Hugh
I hope you had a good Christmas.

So I have a database join on the parent form 'tbl_work_sheets___im_data option' which is populated with a dynamic set of values and descriptions.

Then in a repeat group I have a field 'tbl_work_sheets_56_repeat___im_description'.
I watch a calc element to open the correct number of repeat groups.

Then I used Bauers code to populate the repeat group elements, which it does very nicely, but I only want to insert the value of the dropdown into the field (then hide it) and insert the label into the label of the element, or into a display element.

I could use 2 fields, one as the label , but then I would be storing data multiple times.





Code:
console.log("hey");

jQuery("select#tbl_work_sheets___im_data option").each( function() {
        var optTxt = jQuery(this).text(); // get label of dropdown on parent
        var optVal = jQuery(this).val(); // get value of dropdown on parent       
       
        setTimeout(
            function()
            {
               jQuery("input[id^='tbl_work_sheets_56_repeat___im_description_']").each( function() {
                    if(jQuery(this).val() == ""){ // if the field is empty

                        jQuery(this).val(optVal); // insert value into im_description field to store in database
                       
                        // write label to im_description label
                        //**not working** jQuery(this).text(optText);

                        //**not working** form.formElements.get('tbl_work_sheets_56_repeat___im_description').setLabel(optText);

                        //**not working** var label = document.getElementById('labeltbl_work_sheets_56_repeat___im_description');
                        //label.value=optText;


                        jQuery(this).attr('readonly','readonly');
                        return false;
                    } else {
                        jQuery(this).attr('readonly','readonly');
                    }
                });
        }, 2000);            
    });
 
I'm not entirely sure what you intend that code to do. What it looks like it does is iterate through every option in the im_data dropdown, and sets your im_description repeats to each value in turn. So if you have (say) 20 options in the im_data dropdown, it'll run through 20 times, setting each of the repeats to each of the 20 values in turn. So at the end, the im_description elements will have the value of the last option from the im_data dropdown.

Which doesn't sound like it's what you want to do? I presume you want to set im_description to the currently selected im_data? And to change it if the im_data selection changes?

But to answer your main question, to set the label of an element, there is a method in the Fabrik element class that does that, but I'd need to know more about how your code is actually called. Do you do it in an element JS event, or a js file, or what?

-- hugh
 
Hello Hugh
Firstly you are correct, I want to display all the labels from the im_data dropdown (for the user to view) and have all the id values from the im_data dropdown to record in my database in the field im_description (perhaps my naming of the field could have been better), along with another value that the user adds in another field. Approximately 100 fields each time.

I do not wish to set im_description to the currently selected im_data, in fact im_data won't be visible.

The js is currently residing in the change event of im_data but personally I prefer to work in the form_X.js file.

I have also tried using both a calc element and a display text element with no success.

Thanks Hugh
 
Last edited:
Hugh
I have managed to achieve what I wanted I will post my solution as soon as I have tidied it up.

Thanks as always
Mono
 
I achieved this by using 2 calc fields, one in my parent form with this code in the calculation field.
Then I set my repeat group to watch this calc element, it will then open the correct number of repeat groups for the count of this query.
My query has a sub query also.


Code:
$option = array(); //prevent problems

$option['driver']   = 'mysql';         
$option['host']     = 'localhost';    // Database host name
$option['user']     = 'randomUser';       // User for database authentication
$option['password'] = 'password';   // Password for database authentication
$option['database'] = 'databaseName';      // Database name


$db = JDatabaseDriver::getInstance( $option );



$subQueryB = $db->getQuery(true);
$subQueryA = $db->getQuery(true);
$query = $db->getQuery(true);


$subQueryA->select('function')
  ->from($db->quoteName('tbl_vehicle_details'))
  ->where($db->quoteName('id') . ' = ' . $db->quote('{tbl_work_sheets___vehicle_raw}'));

$subQueryB->select('parent_id')
  ->from($db->quoteName('tbl_insarea_repeat_relevant_to_function'))
    ->where($db->quoteName('relevant_to_function') . ' IN (' . $subQueryA . ')');

// Create the base select statement.
$query->select('Count(*)')
    ->from($db->quoteName('tbl_insarea'))
    //->where($db->quoteName('state') . ' = ' . $db->quote('1'))
    ->where($db->quoteName('id') . ' IN (' . $subQueryB . ')');
    //->order($db->quoteName('ordering') . ' ASC');

// Set the query and load the result.
//$db->setQuery($subQueryA);
$db->setQuery($query);
//$db->setQuery($query);

try
{
    $result = $db->loadResult();
}
catch (RuntimeException $e)
{
    throw new RuntimeException($e->getMessage(), $e->getCode());
}
//$result = ('{tbl_work_sheets___vehicle_raw}');
return $result;

Then I wanted to display a label on each of my repeat groups, so I placed a calc element in my repeat group with no label called 'im_area_description' with this in the calc.

Code:
return "";

On my parent form I used a database join 'tbl_work_sheets___im_data' with a where clause that had the correct fields I wanted to display on my repeat groups.

In my application I used a button to call this javascript function to populate 'im_area_description', it also populates a hidden field element with the id of each
area.
Code:
function populateImAreas(){
  jQuery("select#tbl_work_sheets___im_data option").each( function() {
     
        var optTxt = jQuery(this).text();
        var optVal = jQuery(this).val();
     
        setTimeout(
      
          function()
            {
           
              jQuery("input[id^='tbl_work_sheets_59_repeat___im_id_']").each( function() {
                    if(jQuery(this).val() == ""){
                        jQuery(this).val(optVal);
                        return false;
                    }
                });
             
             
               jQuery("[id^='tbl_work_sheets_59_repeat___im_area_description_']").each( function() {
              
                    if(jQuery(this).text() == ""){
                        jQuery(this).text(optTxt);
                        return false;
                    }
                });
                  
             
        },2000);          
    });
 
Last edited:
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top