How do I connect collection data to a custom component in a Dynamic Page?

I inherited a Wix site and I have been able to create a Collection, create a Data List Page and a Data Item Page.

In each of those two Pages, I would like to pull a url fragment from the database and write out a custom data element in an iframe. So the field value looks like /example1/test and I need to substitute it into MYENCODEDSTRING (encoded):

<iframe width="100%" height="120" src="MYENCODEDSTRING" frameborder="0" ></iframe>

(actually, there’s a base url in src that I’m appending MYENCODEDSTRING to, but the forum says I can’t post a link)

It seems like it should be straightforward but I’ve spent several hours reading Wix documentation but I’m still confused about what pieces I need to get this to work, and what restrictions there are that might prevent them from working together. I first tried creating a repeater, but the documentation says I can’t put iframes in a repeater. And I can’t see how to connect the data to the field anyway. I also tried connecting a Rich Text Item to data but it just says “not connected”, and it’s not apparent whether I can connect data to an html attribute. I’m wondering if someone can send me in the right direction.

Thanks

Ok, I figured this out—I will clean this code up and post the solution.

Frustratingly, this forum is buggy and I can’t seem to post my code here. It tells me I’m not allowed to post links. I removed all my links and urls in the code and it still prevents me from posting.

EDIT: Apparently it thinks that this is a URL:

iframeElement. id 

Ok, so here is what I came up with to create an iframe on the Data Item page from database data. Hopefully someone else finds this useful—but this is my first experience with Wix, so all caveats apply. I have not really tested this yet either.

I had to edit this file to remove links to work around the bug I mention above.

Specifically I am including mixcloud widgets which look like this:

<iframe width="100%"
     height="120"
     src="REMOVEDSINCEICANTPOSTLINKS"
     frameborder="0" ></iframe>

That encoded fragment, /spartacus/party-time comes from the database.

So first of all, I created Dynamic Pages called MixCloudCasts

This seems to give me a Dynamic List Page which lists all the mixcloud items, and a Dynamic Item Page which displays one item.

I created a Collection (database table) to go along with it. I think I created it from the Dynamic Page dialogue, though I might be mistaken. It has a field “key”, which contains the fragment “/spartacus/party-time”, which is destined for the query string in the iframe src.

So then I created a custom element on the Dynamic Item page via Add => Embed => Custom Embeds => Custom Element. In the Custom Element editor that comes up, I used these settings:

    Element Settings = Velo File
    Select one of your Velo Files = mixcloudPlayer.js
    TagName = mixcloud-player

The widget itself is a standard Custom Element. The editor for this is difficult to find—there’s an icon with curly braces on the left “{}”, then “Public and Backend” => “Public” => “Custom Elements”. My code seems to be there, in the file “mixcloudPlayer.js”.

When I click on it, my code appears in a tab at the bottom of the screen. I replaced what was there with this:

const BASE_URL = "HTTPSMIXCLOUDCOM/widget/iframe/"

const createIFrame = (key) => {
    if (!key) {
        const div = document.createElement('div');
        // I should do a better job of this
        div.textContent = "LOADING...";
        return div;
    }
    const src = BASE_URL + "?hide_cover=1&light=1&feed=" + encodeURIComponent(key);

    const iframeElement = document.createElement('iframe');
    iframeElement.width = "100%"
    iframeElement.height = "120"
    iframeElement.src = src;
    iframeElement.frameborder = "0"
    iframeElement. id = "mixcloud-iframe"
    return iframeElement;
};


class MixCloudPlayerElement extends HTMLElement {
    constructor() {
        super();
        console.log(DEBUG_TEXT);
    }

    static get observedAttributes() {
        return ['key'];
    }

    get key() {
        return this.getAttribute('key');
    }

    set key(newValue) {
        this.setAttribute('key', newValue);
    }

    connectedCallback() {
        const el = createIFrame(this.key)
        this.appendChild(el);
    }

}
customElements.define('mixcloud-player', MixCloudPlayerElement);
 

When the “key” attribute is set, it will render the iframe from that.

So to get the data to the component, at the bottom of the page I have an editor which says “MixCloudCasts (Slug)” which seems to be my Data Item page initialization javascript. I replaced it with this:

$w.onReady(function () {
    $w("#dynamicDataset").onReady(() => {
        let currentCloudCast = $w("#dynamicDataset").getCurrentItem();
        $w('#mixCloudPlayer').setAttribute('key', currentCloudCast.key);
    });
});

It appears you need to nest the onReady commands, as per this post. The ambient dataset (a dataset seems to be the bridge that connects you to the database) is accessible via $w(“#dynamicDataSet”), and I use that to get the current item. Then I send the data item to the player, which I find via $(“#mixCloudPlayer”).

This seems to work when I preview it. But I’d be interested to know if there’s anything I missed.