Pass data to your custom component

Hello,

I am having an issue passing data into my custom component.

My model is as follows:

{
  "link": {{link_token.value}}
}

and my iFrame code is:

<html>
<!--=================================================
    STYLES AND PAGE INSTRUCTIONS. IGNORE THIS STUFF
    =================================================-->
<head>
  <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@700&display=swap" rel="stylesheet">
  
</head>
<body style="background-color:#B1EEFC;">
    <div class="outer">
      <button id="link-button" style="background-color: white;border: #0A85EA;color: black;padding: 12px 32px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19)">Link Account</button>

    </div>
​
<!--=================================================
    PLAID SCRIPTS. HERE'S THE STUFF YOU'LL EDIT!
    =================================================-->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
  <script type="text/javascript">
  (function($) {
    var handler = Plaid.create({
      token: '{model.link}',
      onSuccess: function(public_token, metadata) {
        console.log('public token is:', public_token);
      },
      onExit: function(err, metadata) {
        console.log('onexit invoked');
      },
      onEvent: function(eventName, metadata) {
        console.log('event name is:', eventName);
      }
    });
    $('#link-button').on('click', function(e) { handler.open() });
  })(jQuery);
  </script>
​
</body>
</html>

But for some reason the value of the model is not showing up when I enter {model.link} in my iFrame. What am I doing wrong?

Thanks!

Looks like you are missing the retool required portion in your iframe

<script
  src="https://unpkg.com/react@18/umd/react.development.js"
  crossorigin
></script>

<script
  src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
  crossorigin
></script>

<div id="react"></div>
<script type="text/babel">
  const MyCustomComponent = ({ triggerQuery, model, modelUpdate }) => (
    <p>Hello, {model.name}!</p>
  );
  const ConnectedComponent = Retool.connectReactComponent(MyCustomComponent);
  const container = document.getElementById("react");
  const root = ReactDOM.createRoot(container);
  root.render(<ConnectedComponent />);
</script>

EDIT: I pasted the wrong portion, correct should be displayed now.

Develop custom components | Retool Docs

1 Like

Wow! Thanks for the quick reply my friend! I added that portion to my iFrame before my script and sure enough, it did add the "model.link" to the text "Hello..." but how do I then insert that same value into my iFrame code "model.link"?

Thank you again!

Sorry I should have been clearer, wrap your code with the code that I pasted. So, the part I pasted that is below.

"

Hello, {model.name}!

"

is where you will paste your code then it should work.

I cant figure out how to escape it formatting in this forum. I'll circle it and paste it in a moment.

<script
  src="https://unpkg.com/react@18/umd/react.development.js"
  crossorigin
></script>

<script
  src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
  crossorigin
></script>

<div id="react"></div>
<script type="text/babel">
  const MyCustomComponent = ({ triggerQuery, model, modelUpdate }) => (
    
<html>
<!--=================================================
    STYLES AND PAGE INSTRUCTIONS. IGNORE THIS STUFF
    =================================================-->
<head>
  <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@700&display=swap" rel="stylesheet">
  
</head>
<body style="background-color:#B1EEFC;">
    <div class="outer">
      <button id="link-button" style="background-color: white;border: #0A85EA;color: black;padding: 12px 32px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19)">Link Account</button>

    </div>
​
<!--=================================================
    PLAID SCRIPTS. HERE'S THE STUFF YOU'LL EDIT!
    =================================================-->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
  <script type="text/javascript">
  (function($) {
    var handler = Plaid.create({
      token: '{model.link}',
      onSuccess: function(public_token, metadata) {
        console.log('public token is:', public_token);
      },
      onExit: function(err, metadata) {
        console.log('onexit invoked');
      },
      onEvent: function(eventName, metadata) {
        console.log('event name is:', eventName);
      }
    });
    $('#link-button').on('click', function(e) { handler.open() });
  })(jQuery);
  </script>
​
</body>
</html>


  );
  const ConnectedComponent = Retool.connectReactComponent(MyCustomComponent);
  const container = document.getElementById("react");
  const root = ReactDOM.createRoot(container);
  root.render(<ConnectedComponent />);
</script>

Remove your comments if it still doesn't work, if I'm remember correctly I had to comment
/* like this */ instead of standard html comments

1 Like

Thanks again. I tried that but it didn't work. I noticed the bottom of the code you pasted might be in the wrong place maybe? i.e. " ); const ConnectedComponent... "

Sorry to keep bugging but I really do appreciate you!

Thanks!

No worries,

This is code directly from a componant I have that is generating a SVG, its working.

<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.8.0/html2pdf.bundle.min.js" crossorigin></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js" crossorigin></script>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>


<div id="react12"></div>

<script type="text/babel">

    const SVGComponent = ({ model }) => (
        

PUT YOUR CODE HERE

    );


    const ConnectedSVGComponent = Retool.connectReactComponent(SVGComponent);
    const container = document.getElementById("react12");
    const root = ReactDOM.createRoot(container);
    root.render(<ConnectedSVGComponent />);
</script>
  
  


</div>

</body>
</html>

I'm unsure of the function of your code and what its supposed to be displaying, I do see the issue on my end as well though. Attempting to fix it.

Ok, this is failing to load the library it seems like, but I can see your link button for a millisecond during reload. Figure out what's going on with the Plaid library and fix the token key I just threw some numbers into and see what happens.

<!DOCTYPE html>
<html>

<head>
  <title>React and Plaid</title>
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" crossorigin></script>
  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js" crossorigin></script>
</head>

<body style="background-color:#B1EEFC;">
  <div id="react1"></div>
  <div class="outer">
    <button id="link-button" style="background-color: white;border: #0A85EA;color: black;padding: 12px 32px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19)">Link Account</button>
  </div>
    <script type="text/javascript">
    // Plaid initialization code
    (function($) {
      var handler = Plaid.create({
        token: '88888',
        onSuccess: function(public_token, metadata) {
          console.log('public token is:', public_token);
        },
        onExit: function(err, metadata) {
          console.log('onexit invoked');
        },
        onEvent: function(eventName, metadata) {
          console.log('event name is:', eventName);
        }
      });

      // Event binding using jQuery (consider using React event handling instead)
      $('#link-button').on('click', function(e) {
        handler.open();
      });
    })(jQuery);
  </script>

  <script type="text/babel">
    // React component definition
    const SVGComponent = () => {
      return (
        <div>
        </div>
      );
    };

    // Render the React component to the container
    const container = document.getElementById("react1");
    const root = ReactDOM.createRoot(container);
    root.render(<SVGComponent />);
  </script>


</body>

</html>
1 Like

Interesting why its doing that. Below is a sandbox token that we can use to test. It's from a test staging environement but that is basically what I have in my model and what I want to pass onto the iFrame.

link-sandbox-ee944336-f7e1-4156-9d71-3a9d7b8be6c6

Thank you again!

I'm unable to test for you right now, but I'm fairly sure this is a problem w mixing jQuery and React. There's 2 common proplems that can pop up, how both languages manipulate the DOM and how events are handled. With jQuery, u usually directly edit a node by selecting then modifying. With frameworks like React they, for the most part, generate the DOM from data then regenerate parts when values change and in Reacts case, it can optimize this by reusing DOM nodes. The biggest problem is that jQuery and React don't know about each other, so if one generates a new DOM and the other is expecting something to be there, its a problem.

TLDR; For your problem and considering how @stevenhdsdoor said he saw the correct value for a split second on refresh, jQuery is attaching the .on() event to the button, then React is regenerating the DOM including the button which now no longer has the .on() event attached to it.

<!DOCTYPE html>
<html>

<head>
  <title>React and Plaid</title>
  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" crossorigin></script>
  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js" crossorigin></script>
</head>

<body style="background-color:#B1EEFC;">
  <div id="react1"></div>
  <div class="outer">
     <!-- we want to render the button here -->
  </div>
  <script type="text/babel">
    // React component definition
    const SVGComponent = () => {
        const handler = () =>{ 
            Plaid.create({
            token: '88888',
            onSuccess: function(public_token, metadata) {
               console.log('public token is:', public_token);
            },
            onExit: function(err, metadata) {
              console.log('onexit invoked');
           },
        onEvent: function(eventName, metadata) {
           console.log('event name is:', eventName);
        }
      });
    }
        const btn_style = {
            background-color: "white"
        }
      return (
        <div>
            <button id="link-button" style={btn_style} onClick={handler} >Link Account</button>
        </div>
      );
    };

    // Render the React component to the container
    const container = document.getElementById("outer");
    const root = ReactDOM.createRoot(container);
    root.render(<SVGComponent />);
  </script>


</body>

</html>

I haven't slept in a couple days, so I appologize for mixing languages/syntax and any other ridiculous errors I managed to make (I'ma be happy if there's no logic errors honestly). You probably could leave the function the way you had it, but Steven already gave the code for the component so might as well use it?

Hello again my friend,

Were you able to use the sandbox token to get it working on your end?

Thanks,

Hi Steven,

I had to create a new sandbox link token as that one expired:

link-sandbox-d8741658-5a14-42ec-9ab7-3730b4645813

Let me know if you have a chance to take a look at it :slight_smile:

Thanks!

I was able to get it done this way and it worked:

My model is like this:

{
  "link": "{{link_token.value}}"
}

And my iFrame is like this:

<html>
<!--=================================================
    STYLES AND PAGE INSTRUCTIONS. IGNORE THIS STUFF
    =================================================-->
<head>
  <link href='https://fonts.googleapis.com/css?family=Poppins' rel='stylesheet'>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap" rel="stylesheet">
  
</head>
<body style="background-color:#B1EEFC;">
    <div class="outer">
      <button id="link-button" style="background-color: white;border: #0A85EA;color: black;padding: 12px 32px;text-align: center;text-decoration: none;display: inline-block;font-size: 14px;margin: 4px 2px;box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19)">+ Add New Bank or Credit Card Account</button>

    </div>
  
<script
  src="https://unpkg.com/react@18/umd/react.development.js"
  crossorigin
></script>

<script
  src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
  crossorigin
></script>
  
  


<!--================================================
    PLAID SCRIPTS. HERE'S THE STUFF YOU'LL EDIT!
    =================================================-->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
  <script type="text/javascript">
  window.Retool.subscribe(function (model) {
    var handler = Plaid.create({
      token: model.link,
      onSuccess: function(public_token, metadata) {
        console.log('public token is:', public_token);
      },
      onExit: function(err, metadata) {
        console.log('onexit invoked');
      },
      onEvent: function(eventName, metadata) {
        console.log('event name is:', eventName);
      }
    });
    $('#link-button').on('click', function(e) { handler.open() });
  })(jQuery);

  </script>
​
</body>
</html>

Thanks for all the help. Hope this helps someone that was a little stuck like me!

Thanks!

1 Like