Custom side panel: Wait for data

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Stefan
    Member
    • Jul 2021
    • 57

    Custom side panel: Wait for data

    Hi!

    I've tried to create a custom sidepanel. It sometimes works, but not always.

    It looks as if
    Code:
    this.model.get('cOffeneKursgeb')
    is not always defined when loading the panel. Is there a way to wait for it?​

    Code:
    define(['views/record/panels/side'], (SidePanelView) => {
        return class extends SidePanelView
        {
            templateContent = ''
            
            setup() {
                super.setup();
                // Trigger fetching the data
                this.model.fetch();
                const offen = this.model.get('cOffeneKursgeb'); // Access after data has loaded
                console.log(offen);
                if (offen === 0 || offen === null)
                {
                    this.templateContent = "";
                }
                else
                {
                    console.log("set");
                    this.templateContent =
                        "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" +
                        "€" + offen + ",00</div>";
                }
            }
        }
    });
    ​
  • Firyo
    Senior Member
    • Jun 2022
    • 134

    #2
    Hi,

    Your issue here is the
    PHP Code:
    this.model.fetch(); 
    
    that does an async request to the espo back-end.
    The fix would be to wait for the model to be fetched before executing the other batch of code.

    You'll also need to tell your view to wait for the data to load before continuing its workflow.

    See :



    Regards,
    Firyo.

    Comment

    • Stefan
      Member
      • Jul 2021
      • 57

      #3
      Thank you very much Firyo !

      That helped me a lot. I now always get the correct value, but the view is not updated afterwards.

      I thought I could do this with
      Code:
      this.reRender();
      but that doesn't work.

      Code:
      define(['views/record/panels/side'], (SidePanelView) => {
          return class extends SidePanelView
          {
              templateContent = "<div>Test</div>";
            
          setup()
          {
              super.setup();
              this.wait(
                  this.getModelFactory()
                      .create('Contact')
                      .then(model => {
                          model.id = this.model.id; // Set the ID for the model
                          return model.fetch({ select: ['cOffeneKursgeb'] });
                      })
                      .then(data =>{
                          console.log(data.cOffeneKursgeb);
                          const offen = data.cOffeneKursgeb;
                          if (offen === 0 || offen === null || !offen)
                          {
                              console.log("null");
                              this.templateContent = "";
                          }
                          else
                          {
                              console.log("set");
                              this.templateContent =
                                  "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" +
                                  "€" + offen + ",00</div>";
                              this.reRender();
                          }
                      })
              );
          }
      
          }
      });​

      Comment

      • Firyo
        Senior Member
        • Jun 2022
        • 134

        #4
        In my opinon, re-rendering the view inside the setup isn't optimal.

        Try this code instead.
        PHP Code:
        define(['views/record/panels/side'], (SidePanelView) => {
            return class extends SidePanelView
            {
                templateContent = "<div>Test</div>";
        
                setup()
                {
                    super.setup();
                    this.wait(true);
        
                    this.getModelFactory()
                        .create('Contact')
                        .then(model => {
                            model.id = this.model.id; // Set the ID for the model
                            model.fetch({ select: ['cOffeneKursgeb'] });
        
                            console.log(data.cOffeneKursgeb);
                            const offen = data.cOffeneKursgeb;
                            if (offen === 0 || offen === null || !offen)
                            {
                                console.log("null");
                                this.templateContent = "";
                            }
                            else
                            {
                                console.log("set");
                                this.templateContent =
                                    "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" +
                                    "€" + offen + ",00</div>";
                                this.wait(false);
                            }
                        });
                }
        
            }
        });

        Comment

        • Stefan
          Member
          • Jul 2021
          • 57

          #5
          Thank you for your help Firyo.

          Unfortanely this doesnt work, because data is not definded.

          I also tried this:

          Code:
          this.getModelFactory()
            .create('Contact')​
            .then(data=> {
               [...]
            }
          but this doesn't update the panel.

          Is there an example somewhere of how to get the data before loading the panel? Unfortunately I haven't found anything.
          Or do you have another idea?​

          Thank you in advance!

          Comment

          • Firyo
            Senior Member
            • Jun 2022
            • 134

            #6
            Oh yes, that's my bad.

            That should work
            Code:
            define(['views/record/panels/side'], (SidePanelView) => {
                return class extends SidePanelView
                {
                    templateContent = "<div>Test</div>";
            
                    setup()
                    {
                        super.setup();
                        this.wait(true);
            
                        this.getModelFactory()
                            .create('Contact')
                            .then(model => {
                                model.id = this.model.id; // Set the ID for the model
                                model.fetch({ select: ['cOffeneKursgeb'] });
            
                                console.log(model.get('cOffeneKursgeb'));
                                const offen = model.get('cOffeneKursgeb');
                                if (offen === 0 || offen === null || !offen)
                                {
                                    console.log("null");
                                    this.templateContent = "";
                                }
                                else
                                {
                                    console.log("set");
                                    this.templateContent =
                                        "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" +
                                        "€" + offen + ",00</div>";
                                    this.wait(false);
                                }
                            });
                    }
            
                }
            });​​

            Comment

            • Stefan
              Member
              • Jul 2021
              • 57

              #7
              Thanks for your help Firyo, but somehow it doesn't work.

              What I really don't understand, I now have this test code:

              Code:
              define(['views/record/panels/side'], (SidePanelView) => {
                  return class extends SidePanelView
                  {
                      templateContent = "<div>Test</div>";
                      setup()
                      {
                          super.setup();
                          this.wait(true);
                          this.getModelFactory()
                              .create('Contact')
                              .then(model => {
                                  model.id = this.model.id; // Set the ID for the model
                                  model.fetch({ select: ['cOffeneKursgeb'] });
                                  console.log(model);
                                  console.log(model.attributes);
                                  console.log(model.attributes.cOffeneKursgeb);
                                  console.log(model.get('cOffeneKursgeb'));
                                  const offen = model.get('cOffeneKursgeb');
                                  if (!offen)
                                  {
                                      console.log("null");
                                      this.templateContent = "";
                                  }
                                  else
                                  {
                                      console.log("set");
                                      this.templateContent =
                                          "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" +
                                          "€" + offen + ",00</div>";
                                      this.wait(false);
                                  }
                              });
                      }
                  }
              });​
              Code:
              console.log(model);
              shows in field attributes the correct value cOffeneKursgeb
              Code:
              console.log(model.attributes);
              shows an array with the correct value cOffeneKursgeb

              Click image for larger version

Name:	sc01.png
Views:	63
Size:	3.7 KB
ID:	112023


              Code:
              console.log(model.attributes.cOffeneKursgeb);​
              returns undefined
              Code:
              console.log(model.get('cOffeneKursgeb'));
              returns undefined


              How is that possible?

              Comment

              • Firyo
                Senior Member
                • Jun 2022
                • 134

                #8
                Okay I just took my time to read your answer and we missed something here, I'll try to explain it well.

                What you see in your console isn't really relevant because in Javascript, every variable you pass into functions are given by "reference" (opposed to "value").

                The issue we're encountering now is the fetch that is taking some time to actually retrieve the data of the model but our code logic isn't waiting for it to do its job.

                Code:
                define(['views/record/panels/side'], (SidePanelView) => {
                    return class extends SidePanelView
                    {
                        templateContent = "<div>Test</div>";
                        setup()
                        {
                            super.setup();
                            this.wait(true);
                            this.getModelFactory()
                                .create('Contact')
                                .then(model => {
                                    model.id = this.model.id; // Set the ID for the model
                                    model.fetch({ select: ['cOffeneKursgeb'] }).then(() => { // We now wait for the fetch function to end its process to continue our code logic
                                        console.log(model);
                                        console.log(model.attributes);
                                        console.log(model.attributes.cOffeneKursgeb);
                                        console.log(model.get('cOffeneKursgeb'));
                                        const offen = model.get('cOffeneKursgeb');
                                        if (!offen)
                                        {
                                            console.log("null");
                                            this.templateContent = "";
                                        }
                                        else
                                        {
                                            console.log("set");
                                            this.templateContent =
                                                "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" +
                                                "€" + offen + ",00</div>";
                                            this.wait(false);
                                        }
                                    });
                                });
                        }
                    }
                });​​
                This time, hopefully, it's working

                Comment

                • Stefan
                  Member
                  • Jul 2021
                  • 57

                  #9
                  Thank you Firyo for your help and also for the explanation, I really appreciate that!

                  Unfortunately it still does not work.

                  Even if we get in here (i.e. console outputs "set"):

                  Code:
                  console.log("set");
                  this.templateContent = "<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>" + "€" + offen + ",00</div>";
                  this.wait(false);​
                  The panel still shows Test. So the templateContent has not been updated. Or it was updated but the view was not updated? But if I have understood correctly, we are actually waiting until here to render the view:
                  Code:
                  this.wait(false);

                  Comment

                  • Firyo
                    Senior Member
                    • Jun 2022
                    • 134

                    #10
                    Ok, I don't use often "templateContent" so I wasn't aware of something (that is blocking us).
                    You can't override templateContent in your JS logic code, it will stay at it was set in the first place.

                    Here's the new code
                    Code:
                    define(['views/record/panels/side'], (SidePanelView) => {
                        return class extends SidePanelView
                        {
                            templateContent = `<div style='color: var(--link-color); font-size: 2rem;font-weight: 500; padding-top: 5px;'>{{value}}</div>`;
                            value = null;
                            setup() {
                                super.setup();
                                this.wait(true);
                                this.getModelFactory()
                                    .create('Contact')
                                    .then((model) => {
                                        model.id = this.model.id; // Set the ID for the model
                                        model.fetch({ select: ['cOffeneKursgeb'] }).then(() => { // We now wait for the fetch function to end its process to continue our code logic
                                            console.log(model);
                                            console.log(model.attributes);
                                            console.log(model.attributes.cOffeneKursgeb);
                                            console.log(model.get('cOffeneKursgeb'));
                                            const offen = model.get('cOffeneKursgeb');
                                            if (!offen)
                                            {
                                                console.log("null");
                                                this.wait(false);
                                            }
                                            else
                                            {
                                                console.log("set");
                                                this.value = `€ ${offen} ,00`;
                                                this.wait(false);
                                            }
                                        });
                                    });
                            }
                            data() { // this is triggered before the template is rendered
                                const data = super.data();
                                data.value = this.value;
                                return data;
                            }
                        };
                    });​

                    Comment

                    • Stefan
                      Member
                      • Jul 2021
                      • 57

                      #11
                      That works! ? Thank you very, very much Firyo!!

                      Comment

                      Working...