Repeater (faq accordion style) with a button that changes from "+" to "-"

Hi everybody.

As a novice, I wish the button (#button1AV) to change to “-” when the text is visible and back to “+” when the element closes.

here the script I have done right now :

$w . onReady ( function () {
initAVrepeater ();

function initAVrepeater ( ) {
$w ( ‘#AVrepeater’ ). forEachItem (( $item ) => {
$item ( #buttonAv1 ). onClick (() => {
$item ( #textAv1 ). collapsed ? $item ( #textAv1 ). expand () : $item ( #textAv1 ). collapse ()

I don’t know what function to use and where to integrate it in my script above.

Could someone help me?
Thanks a lot

You might want to post this question on the Velo forum, where you’ll find more people with expertise:

I’m a Velo beginner, but, FWIW, my code was a bit different. I tested it, and it works. That is, when you click the button in any specific repeater item, the text in that item (textBox) expands and the label on the button (expandBtn) for that item is changed to ‘-’.

If you click that button again, in the same item, the text box collapses and the button label reverts to ‘+’.

export function expandBtn_click(event) {
     let $item = $;
    if ($item('#textBox').collapsed) {
        $item('#textBox').expand() ;
        $item('#expandBtn').label = "-";
    } else {
         $item('#textBox').collapse() ;
        $item('#expandBtn').label = "+";

I’m using $ to ensure I’m dealing with the specific repeater item where the click occurred.

Again emphasizing that I’m a beginner, I don’t think ‘forEachItem’ is the best way to establish ‘onClick’ behavior in a repeater. ‘At’ seems to be intended for that purpose. See the documentation: at - Velo API Reference -

Note: If you want any already-expanded items to close whenever you expand a different item (that is, if you want only one item to show at a time), you’d need to add a bit of code to collapse any other expanded items when a new item is expanded.

Here’s another version where I permit only one text box to be expanded at a time. Note that I use ‘forEachItem’ to perform a function on each item but ‘at’ where I wanted to deal with the specific item where the click occurred.

Also note (because I don’t think it’s obvious when you just glance at the code) that I’ve got a NOT operator (!) in front of the boolean that’s testing to see if the textBox is collapsed).

function closeOpenItems() {
  $w("#myRepeater").forEachItem(($item, itemData, index) => {
    if (!$item("#textBox").collapsed) {
      $item("#expandBtn").label = "+";

export function expandBtn_click(event) {
  let $item = $;
  let isCollapsed = $item("#textBox").collapsed;
  if (isCollapsed) {
    $item("#expandBtn").label = "-";
1 Like

Hi Jim,
Thanks for your help and advices. I will also post this question on Velo Forum to get more info about the best way to reach my goal.
Thanks again and have a nice weekend.

Good luck with the Velo forum.

Meanwhile, I suggest you give my code a try. I’ve tested both examples, and they work.

The first example toggles each item independently. Once an item is expanded, it is left expanded until it is explicitly collapsed. As a result, multiple items can be in expanded mode at any one time.

The second example allows only one item to be expanded at a time. Whenever you expand one item, any other expanded item is collapsed.

Both examples toggle the button between ‘+’ and ‘-’.

Your way of thinking is correct, but this one also could be useful for you…

You are using…

let $item=$;

But i have to say, there are better ways…

Also i see you are working with …



Hmmm, yeah, probably in some cases this method is not bad, but in general, perhaps you should consider to work INSIDE → onReady(). I hope you understand what i mean.

It has its ADVANTAGES, believe me!

1 Like