Trying to overcome limitations

Question:
How do I overcome limitations to achieve hierarchical nested page contents via dynamic content?

Product:
Wix Studio Editor

What are you trying to achieve:
I am trying to create multi-tiered nested hierarchical page contents for a dynamic page, using data pulled from a CMS collection. The purpose would be to create anchor-linked contents so that users can jump to page sections as required.

The best way to describe the nesting is: Parent Page (with an initial body text) → Section → Subsection.

What have you already tried:
I can seem to get my hierarchy to be recognised, as well as the tiers. But regardless of using 3 separate repeaters, or a single repeater, there seems to be no way to create the necessary visual representation on page.

I can’t manipulate values to alter padding/margins or anything to create indentation based on section.

I can’t alternate items between multiple repeaters in a single hierarchy.

I can’t access custom code to apply CSS until I upgrade and add a domain, the issue with this is that I am designing this site to replace an existing site built on the standard editor, so upgrading/buying a domain for it is not only counter intuitive, but also I am doing this for my employer where unnecessary cost won’t be very welcome, especially when all previous limitations leads me to believe that I might not even be able to achieve my requirements.

Am I overcomplicating things for myself?

Additional information:
Let me know if there is any info I can provide?

1 Like

Not going to pretend I fully follow what you are trying to do, and I fully under stand your frustrations with the limits before an upgrade. I to have found my self not only in the same situation but also thinking exactly the same while pulling my hair out.

I stumbled across this just before the last hair follicle came out.
You can get up to five premium dev sites free to test on. They are meant to test apps for the market place. But you can use them to see and do the stuff that is not available in the non upgraded site. One limitation it seems though is they are only created in Wix Editor not Studio. That’s fine for me since I HAVE to use wix editor for my build.

see

2 Likes

The best way, is to generate your own solution in your case!

Wix do provide elements like…

  1. REPEATERS → available on all Wix Editors
    —> Repeater Introduction | Velo

  2. MULTISTATE-BOXES —> available on Wix-Editor & Wix-Studio
    —> Multi State Box Introduction | Velo

  3. ACCORDION-MENUS → only available in Wix-Studio
    —> Accordion Introduction | Velo
    Some more infos about ACCORDION-MENU…
    Adding info to an accordion with code

  4. IFRAME/HTML-COMPONENT → available on all Wix-Editors → PAID-PLAN
    —> Html Component Introduction | Velo

  5. CUSTOM-ELEMENT → available on all wix-editors → PAID-PLAN
    —> Custom Element Introduction | Velo

You have already mentioned some of those, and you also have already recognized their boundaries.

To work totaly free of boundaries → your only way will be to get a paid plan → and generate your own solution → using a CUSTOM-ELEMENT.

Why?

REPEATER-PROBLEM: → is wix already capable to put REPEATER into another REPEATER ? → i don’t think so, at least it was not possible in last decades.

ACCORDION-PROBLEM: → my last UPDATE of ACCORDIONS was → they are very limited.

MSB (Multi-State-Box)-PROBLEM: → Are you able to put a REPEATER into a MSB or vice-versa? → Try it out. If it works → maybe a possible solution.

HTML-Comp.-PROBLEM: → Only available on a PAYED-PLAN. Also do not support CSS and not RESPONSIVE.

CUSTOM-ELEMENT: → PAYED-PLAN, but SEMI-RESPONSIVE because supporting CSS.

As you can see → A LOT OF PROBLEMS AND BOUNDARIES.

The best SOLUTION for you would be to use a CUSTOM-ELEMENT !!!
This way, you would be able to generate what ever you like, what ever you want, without beeing cropped by all the restrictions.

You need a simple example of how to generate an own ACCRODION-MENU ?

Here we go…

1) Open Js-Fiddle…

2) Put in this code into the HTML-SECTION

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Accordion Menu Example</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    <style>
        /* Styling for the accordion menu */
        .secWrapper {
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }

        .secLabel {
            background-color: #3f3f3f;
            color: white;
            cursor: pointer;
            padding: 10px;
            text-align: left;
            font-weight: bold;
            border-radius: 5px;
        }

        .secLabel:hover {
            background-color: #505050;
        }

        .secContent {
            display: none;
            padding: 10px;
            background-color: #f4f4f4;
            border-radius: 5px;
            margin-top: 5px;
            transition: max-height 0.3s ease-out;
            max-height: 0;
            overflow: hidden;
        }

        .secContent.open {
            display: block;
            max-height: 500px; /* Allow content to expand */
        }

        .secContent p {
            margin: 5px 0;
        }
    </style>
</head>
<body>

<div id="appContainer"></div>

<script>
    function start_process(APP, data, divParent, keyTitle = 'Root', depth = 0, firstParentTitle = null, counters = { total: 0 }) {
        const secMain = createSecMain();
        if (secMain) {
            divParent.appendChild(secMain);
        } else {
            console.error('secMain is not a valid node.');
        }

        if (data instanceof Object && !Array.isArray(data)) {
            handleObject(APP, data, secMain, keyTitle, depth, firstParentTitle, counters);
        } else if (Array.isArray(data)) {
            handleArray(APP, data, secMain, keyTitle, depth, firstParentTitle, counters);
        } else {
            console.error('Unknown data type');
        }
    }

    function createSecMain() {
        const secWrapper = document.createElement('div');
        const secLabel = document.createElement('div');
        const secContent = document.createElement('div');
        
        if (secWrapper && secLabel && secContent) {
            secWrapper.classList.add('secWrapper');
            secLabel.classList.add('secLabel');
            secContent.classList.add('secContent');
            secWrapper.appendChild(secLabel);
            secWrapper.appendChild(secContent);
            secWrapper.childContent = secContent;
        } else {
            console.error('Error creating section wrapper or content');
            return null;
        }
        return secWrapper;
    }

    function handleObject(APP, data, divParent, keyTitle, depth, firstParentTitle, counters) {
        const secWrapper = create_CollapsibleSection(keyTitle, null, true, depth);

        if (secWrapper) {
            divParent.appendChild(secWrapper);
            counters.total++;

            for (let key in data) {
                if (data.hasOwnProperty(key)) {
                    const childData = data[key];
                    if (typeof childData === 'object' && !Array.isArray(childData)) {
                        handleObject(APP, childData, secWrapper.childContent, key, depth + 1, firstParentTitle, counters);
                    } else if (Array.isArray(childData)) {
                        handleArray(APP, childData, secWrapper.childContent, key, depth + 1, firstParentTitle, counters);
                    } else {
                        const pElement = document.createElement('p');
                        pElement.textContent = `${key}: ${childData}`;
                        secWrapper.childContent.appendChild(pElement);
                    }
                }
            }
        }
    }

    function handleArray(APP, data, divParent, keyTitle, depth, firstParentTitle, counters) {
        const secWrapper = create_CollapsibleSection(keyTitle, null, true, depth);

        if (secWrapper) {
            divParent.appendChild(secWrapper);
            counters.total++;

            data.forEach(item => {
                const itemElement = document.createElement('div');
                itemElement.textContent = JSON.stringify(item); // Convert array items to string for display
                secWrapper.childContent.appendChild(itemElement);
            });
        }
    }

    function create_CollapsibleSection(labelText, childElement, isExpanded, depth = 0) {
        const secWrapper = document.createElement('div');
        const secLabel = document.createElement('div');
        const secContent = document.createElement('div');
        
        secLabel.classList.add('secLabel');
        secLabel.textContent = labelText || 'Unnamed Section';

        secContent.classList.add('secContent');
        secContent.style.display = isExpanded ? 'block' : 'none';
        
        if (childElement instanceof HTMLElement) {
            secContent.appendChild(childElement);
        }

        secWrapper.classList.add('secWrapper');
        secWrapper.appendChild(secLabel);
        secWrapper.appendChild(secContent);

        secWrapper.childContent = secContent;

        secLabel.addEventListener('click', function() {
            secContent.classList.toggle('open');
        });

        return secWrapper;
    }

    // Example usage:
    const divParent = document.getElementById('appContainer');
    const data = {
        name: 'Example',
        description: 'This is an example data structure.',
        details: {
            type: 'Example Type',
            isActive: true
        },
        items: ['item1', 'item2', 'item3']
    };
    start_process(null, data, divParent);
</script>

</body>
</html>

3) Save and run it! (to save → CTRL+S)

4) Take a look onto the RESULT!

5) Take a look onto the DATA.

const data = {
        name: 'Example',
        description: 'This is an example data structure.',
        details: {
            type: 'Example Type',
            isActive: true
        },
        items: ['item1', 'item2', 'item3']
    };
  1. Have fun and expand the possibilities of your own ACCORDION-MENU, by adding more features and function and making your accordion code more flexible and robust!

GOOD-LOOK !!!

EDIT:

7) —> CONNECT IT TO YOUR WIX-DATABASE! → and serve data from your wix page to custom element and vice-versa!

What could be your next steps?

  1. Expanding functionalities by adding the following functions to your new generated ACCORDION-MENU…

a) implementation of IMAGE-SUPPORT (SVG, JPG, GIF and so on…)
b) implementation/upgrade of deep level - recursive data construction.
c) table recognition
d) and so on …
e) and so on …
f) and so on …

None of the Wix elements will be capable to handle such a complexity.
The REPEATER would be in this case the most advanced of provided Wix-Elements.

ADDITIONAL READ-STUFF:
Read all his POSTS → Could be very useful. He is a tricky guy who also searches for own solutions.

  1. Custom Element but In Repeater `need answer`

  2. Here you will get more informations…
    Custom Components Integrated into Editor + React.js

1 Like

That is an interesting suggestion to be honest, I don’t 100% know if I can utilise it with what I’m trying to do at present, but its good info nonetheless. Thank you for taking the time.

I guess that climbing over the paywall might be the solutions to all my problems. But it also might be considerably more dev work and time, unfortunately this not being my primary job and having other projects on my hands could make this route untenable.

I appreciate your response, it is something I can explore, if not right now - potentially later down the line. Thank you.

I’m exploring some more unconventional workarounds today, that would instead place more responsibility for precise content management on those who will administrate the CMS - thankfully that will be mostly me for the foreseeable future.

Take your time. Good coding (SOLUTION) needs time!