[SOLVED] Hide repeat group if empty

Status
Not open for further replies.
I have a list with several repeat groups and I'm using a custom template to display the Details view. If any of the groups are empty (i.e. no data entered), I need them to be hidden. However, the Group label is still displayed (along with the table header for one column!).

I found a possible straightforward solution in this forum post: fabrikar.com/forums/index.php?threads/hide-repeat-group-table-if-empty.45899 which made sense to me, so I copied the line:
if (count($group->subgroups) > 0) :
To make it work in my custom template, I amended it as I have specified the name of each group. So where I have a line:
$reviews = $this->groups['reviews'];
I changed the if statement to:
if (count($reviews->subgroups) >0) :

But this didn't work. The empty group still displayed the group label. However, when I changed the line to:
if (count($reviews->subgroups) >1) :
it partially worked. The empty group was hidden, while a record with two rows in the "reviews" table was displayed correctly. Unfortunately, of course, a record with only one row in the "reviews" table was also hidden.

It looks like the code is working and there are no rows for the empty group in the database table. So why does the ">0" line not work? Does Fabrik create an empty subgroup? Is there a solution or a better way to achieve this?

Thank for any guidance.
 
Yes, Fabrik has one hidden subgroup for repeat tables even when there's no records in database for that group, so this is a bit tricky.

There is probably more than one way to solve it, but I think you could do something like this:

1) Initially hide the group with css like:
Code:
#groupXX {
    display:none;
}
Add this to your details template custom css file.

2) Now, in details_xx.js, check some element for existing data that always has some data when the repeat row(s) exist (like id element), so add something like:
Code:
window.addEvent('domready', function(form) {
    var some_text = jQuery('#tablename_xx_repeat___id_ro_0').text().trim().length;
    if(some_text > 0) {
       //data exists in the element, show the repeat group
       jQuery('#groupXX').css('cssText', 'display: block!important;');
    }
});

Haven't tested this exact code, so you might need to adjust. So this is just something to play with. Of course do not forget to change group / element names to match yours (check with browser inspect tool if needed).

This example is just for one group, but you can expand this to multiple groups with jQuery each function or just duplicate the code for each group.
 
Last edited:
Thanks @juuser, that's brilliant.

I think I understand how that works, although I'm a complete JavaScript novice and have never tried jQuery. It won't work for me just yet because I completely re-wrote my custom Details template default.php, stripping out the need for loading the other templates and removing most of the original classes and id's, including the group name id! I'll have a play with it tomorrow and let you know.
 
Sorry @juuser. That worked perfectly for all the text-based repeating groups. But I also need to hide two other items if they are empty:
1) a non-repeating group, which just has a field element and a file upload element.
2) a single file upload element in a group

If I use the standard detail template, these are hidden if empty: I assume it's due to the fabrikDataEmpty class, (I've got the fabrikDataEmpty {display:none; } line in my custom css file). But it won't work in my custom template as I'm not using all the classes and I can't work out how the fabrikDataEmpty class works in the standard template! And I can't work out how to adapt your JavaScript code to cope with the above. :confused:
 
For that of course you can use predefined element js actions, but I usually prefer the css/js way to prevent the element "flashing" before it will get hidden. So basically the same approach above should also work in these cases.

For the first case (non-repeating group) , you should be able use exactly the same approach like above. If there's no value in element, it still has empty element div container with the id like tablename___elementname_ro. So check the field element for existing data in detsils_xx.js.

For the second case, it's a bit more tricky as it seems that Fabrik does not add fabrikDataEmpty class for the empty fileupload elements. And it doesn't add "table___elementname" class to row containers ("row-fluid fabrikElementContainer" classes). So I would first try to modify the details template that it would have "tablename_elementname" class in the "row-fluid fabrikElementContainer " div. And then again use the same approach as above. First hide the row in custom css like:

Code:
.fabrikElementContainer .tablename___elementname {
    display:none;
}

and for the fileupload element in details_xx.js something like:
Code:
window.addEvent('domready', function(form) {
    if ( jQuery('.fabrikElementContainer .tablename___elementname').find('.fabrikSubElementContainer').children().length > 0 ) {
       //data exists in the element, show element
       jQuery('.fabrikElementContainer .tablename___elementname').css('cssText', 'display: block!important;');
    }
});
 
Thanks @juuser, I really appreciate your help.

Unfortunately I can't get either of those to work, probably due to something stupid I've done!

I need to expand on the exact situation. The first case (non-repeating group) is a slideshow; there are two elements: a simple text field which contains a label "Photographs by" and the text field to name the photographer. We may not always know the photographer, so I can't rely on this text field to hide the whole group. The second element is a fileupload for multiple images. To create the slideshow I have created a Visualization which I have then popped into the group outro using the code {fabrik view=visualization id=1 productions___id=[rowid]}. Not sure if this is the correct approach but it works!

So to try and hide this as above, I have added a div around the two elements with an id of "slideshowgroup" and added
Code:
#slideshowgroup {display: none;}
to the custom css file. This hides the group successfully. However, I cannot get the JavaScript to display the group if data exists, either for the text element (which I don't want to use anyway!) or for the fileupload element.

For the second case, I have added the class tablename___elementname to the div so it looks like this:
Code:
<div class="span4 fabrikElementContainer productions___artwork">
        <?php echo $artwork; ?>
    </div>
The variable $artwork I have defined earlier in the file as
Code:
$artwork = $elements['artwork']->element;

However, when I add
Code:
#$form .fabrikElementContainer .productions___artwork {
    display:none;
}
to the custom css file, it doesn't hide the element. I tried it without the #$form as well but still no effect. I haven't progressed to the JavaScript yet as obviously I need to hide it first!

As you can tell, I don't fully know what I'm doing so I've probably missed a step along the way. :oops:
 
Hmm, without access to your site it is difficult to see what exactly is going. With this kind of stuff, every smallest detail can be important.

For the first case, this should work in theory (as I understand that the group should be hidden if there are no files in fileupload element).
Code:
window.addEvent('domready', function(form) {
    if ( jQuery('#slideshowgroup').find('.fabrikSubElementContainer').children().length > 0 ) {
       //data exists in the element, show group
       jQuery('#slideshowgroup').css('cssText', 'display: block!important;');
    }
});

And for the second case, you have extra "#$form" which seems odd and unnecessary, so start by removing it so you'll have:
Code:
.fabrikElementContainer .productions___artwork {
    display:none;
}
 
Thanks @juuser

I’ll try the first one. That will probably work as my previous elements didn’t look like that!

As for the unhideable second case, I did try it without the “#$form” and it still didn’t work. I’ll have another look at it later today.

Thank you!
 
Hi @juuser

Unfortunately, neither is working!

In the slideshow element, the custom css code hides the whole div successfully. At first the JavaScript didn't unhide the div, but then I realised that I didn't have a div with class "fabrikSubElementContainer" in that group. So I changed the div around the slider to "fabrikSubElementContainer", which un-hid the slider in ALL records, including those where there were no file uploads. What I see in those records is just the label for the text element "Photographs by".

As for the single fileupload element, I finally got the custom css to hide the image by removing the space between the two classes (!):
Code:
.fabrikElementContainer.productions___artwork {
    display:none;
}

However, this only hid the image, not the space. This must be because I have wrapped it in a "span4" div. But no matter how I try to adjust the HTML, I can't achieve what I need (i.e. no space if there is no image). Here's what I have:
Code:
<div class="row-fluid">
    <div class="span4">
        <div class="row-fluid fabrikElementContainer productions___artwork">
            <?php echo $artwork; ?>
        </div>
    </div>
(There's a closing </div> further down)

Also, having hidden the image, I added the JavaScript but it didn't unhide it.

It's driving me mad!

If you have time and want to look at the HTML and CSS, here's one of the pages I'm working on (it's only a test site):
http://www.amdramwebdesign.co.uk/fabrik_productions/index.php/productions/details/1/1
The other records are available under the menu item "All Productions".

Thanks!:(
 
It's a but overwhelming to quickly get a grip on your modified template, but for "production artwork" part, it seems that the extra spaces in between class names are the problem. So this seems to be working for unhiding the artwork:
JavaScript:
if ( jQuery('.fabrikElementContainer.productions___artwork').find('.fabrikSubElementContainer').children().length > 0 ) {
       //data exists in the element, show element
       jQuery('.fabrikElementContainer.productions___artwork').css('cssText', 'display: block!important;');
}

And just some hints:
- D0 not wrap "window.addEvent('domready', function(form) " around every code snipper separately. Just add it once around all the code snippets you want to run on domready event that means when page elements have been loaded.

- You can always check what the variables really contain with "alert" or "console.log functions. E.g.
console.log( jQuery('.fabrikElementContainer .productions___artwork').find('.fabrikSubElementContainer').children().length );
with space in between classes will output "0", but without the space it will output "1" in case artwork fu element exist.
 
Thanks so much for all your help and advice on this @juuser.

The artwork is now unhidden successfully with the amended JavaScript. I still have to work out how to hide the whole div, but that shouldn't be beyond me. And the slider div still won't stay hidden when it's empty, but again, I'll keep trying to work out why. You've given me all the code, I just need to amend it until it works :).

Cheers!
 
Status
Not open for further replies.
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top