Trouble accessing nested object in model

Might be a simple javascript misunderstanding but I'm trying to reference a value of an object in the model. I made a quick example to show what I'm talking about.

I can access model.full_name in the iframe code just fine but whats the syntax for referencing model.name.first? That syntax works on a transformer that's reading in the customComponent.model but it's not working in the iframe itself.

Screenshot 2023-11-10 at 2.07.13 PM

Hi @AlexW - you should be able to access model.name.first exactly as you're suggesting.
This example works for me, and I think is equivalent to yours. If you'd like to share an app export or your full iframe code I'd be happy to take a look at your particular set up.

Thanks! One thing I can see right off the bat is I'm using normal javascript and not React.

Here is the iframe component I'm using (basically the example from your documentation for Custom Components.

<html>
  <body>
    <script>
      function updateName(e) {
        window.Retool.modelUpdate({ name: e.target.value });
      }
      function buttonClicked() {
        window.Retool.triggerQuery("query1");
      }
      window.Retool.subscribe(function (model) {
        // subscribes to model updates
        // all model values can be accessed here
        document.getElementById("mirror").innerHTML = model.name.first || "";
      });
    </script>
    <input onkeyup="updateName(event)" />
    <button onclick="buttonClicked()">Trigger Query</button>
    <div>First name</div>
    <div id="mirror"></div>
  </body>
</html>

and here is the model:

{
  "name":{
    "first":"Bob","last":"Loblaw"
  },
  "full_name": "Bob Loblaw"
}

@AlexW thanks for sharing that - that helps a lot.
It seems that the issue is that when a custom component first subscribes to the model - the first update it gets is an empty model. That means when the browser attempts to evaluate model.name.first, you get an error like Uncaught TypeError: Cannot read properties of undefined (reading 'first') which crashes the component and causes the next update with the actual model to not be processed.

You can prevent this from happening by using the conditional operator (ie model.name?.first) or by first checking that the model.name property exists (ie model.name && model.name.first or if(model.name) { //access model.name.first })

I did want to also note that right now, the event handler updateName is setting name to a string, not an object, so after typing in the input model.name will be a string and not have first and last properties any more.

Hope that helps!

4 Likes