Announcement

Collapse
No announcement yet.

Relationship panel refresh on upodates on relatated entity.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Relationship panel refresh on upodates on relatated entity.

    Relationship panel refresh on updates on the related entity.

    I have a scenario where Opportunity: Personal Data (1:M), and the Personal Data are listed under the relationship panel of opportunity.
    We have a status field (enum) for Personal Data. Now the status of personal data gets updated, I want the relationship panel containing the Personal Data under the Opportunity should refresh and show the updated data in the relationship panel.
    How can I add this in javascript?

    1. On status updates with Personal Data
    2. On new Personal Data entity created and linked to Opportunity

    I want the relationship panel to refresh automatically and show the data.

    I tried with: espocrm/client/src/views/record/panels/relationship.js customizing and adding the listen even,

    Code:
        this.listenTo(this.model, 'sync', function () {
            this.collection.fetch();
        }, this);
    But this is not getting triggered when the personal data. status is updated. I didn't find any other solution.
    Websocket is enabled and working fine. But as mentioned in the espocrm docs WebSocket won't work for the relationship panel.
    Can anyone please help me with this?
    Last edited by Ananya K; 07-13-2021, 01:07 PM.

  • #2
    Try this code in your custom relationship.js file
    Code:
        this.listenTo(this.model, 'sync', function ()  {
            this.collection.fetch();
            this._parentView.reRender();
        }, this);
    this.collection.fetch() will refresh the relationship view (list)
    this_parentView.reRender() will refresh the Opportunity detail view which contains the relationship view (Personal Data).

    This has to do with the concept of nested views which is widely used in Backbone.js

    One trick that I use to find out "where I am" when working with views, is to inject a console.log directive like: console.log('my script.js this = ',this);

    Comment


    • #3
      telecastg

      The sync will not trigger when the personal data. status gets updated. So refreshing the Opportunity detail view will not help. To update the opportunity detail view we use a socket.

      When actually the sync is get triggered?
      For me, If there are updates in the opportunity detail view it will trigger, otherwise no.

      I want when the relationship panels Personal Data.Status is updated in the backend I want that panel to be refreshed/this.collection.fetch() under Opportunity.

      Any idea how to do this?

      Comment


      • #4
        Hi,

        To detect when an update (new instance or update to existing instance) is made to Personal data, and refresh the parent entity (Opportunity), then try this code:
        Code:
            this.listenTo(this.nestedViews.list.collection, 'sync', function () {
                    this._parentView.reRender();
            }, this);
        The rationale is that within the relationship.js view, the model and Collection are "Opportunity", and this view contains a nested view that holds a list of "Personal Data" records, so you want to detect when the collection of "Personal Data" changes.

        Also the relationship.js is in turn a nested view of the "Opportunity" detail view, so in order to refresh this display you need to invoke the relationship.js parent view.

        Hope this helps
        Last edited by telecastg; 07-15-2021, 01:23 AM.

        Comment


        • #5
          I am getting an Error in the relationship panel if I add the above code in the setup function of the relationship.js

          If I add in the opportunity detail.js also I am getting errors.

          Last edited by Ananya K; 07-15-2021, 05:51 AM.

          Comment


          • #6
            You have to add it in the afterRender function, the nestedViews do not exist until the parent entity has been rendered.

            This code doesn't belong in the Opportunity detail view. You want to work in the linked entity which is handled by the nested view.

            To better understand what you are working with, I suggest that you inject this in the afterRender function of relationship.js
            Code:
            console.log('relationship.js afterRender() this = ',this);
            Open your console and you can see what has been defined.
            Last edited by telecastg; 07-15-2021, 05:58 AM.

            Comment


            • #7
              Code:
                 afterRender: function () {
                     Dep.prototype.afterRender.call(this);
                     this.listenTo(this.nestedViews.list.collection, 'sync', function () {
                     this._parentView.reRender();
                  }, this);
              this is under espocrm/client/custom/src/views/opportunity/detail.js

              Getting errors :
              • Uncaught TypeError: Cannot read property 'collection' of undefined
              • Uncaught TypeError: Cannot read property 'addEventListener' of undefined
              I am using Espocrm 6.1.7
              Last edited by Ananya K; 07-15-2021, 06:05 AM.

              Comment


              • #8
                As I said previously, the code belongs to the relationship.js view NOT to opportunity/detail.js view.

                You are trying to detect events in the related entity Personal Data and to do that you must add your code to the view that is controlling the list of linked Personal Data entities. (the relationship panel)

                You have to define a custom relationship.js view for PersonalData (assuming that you defined the relationship as "personalData") like this:

                custom/Espo/Custom/Resources/metadata/clientDefs/Opportunity.json
                Code:
                    "relationshipPanels": {
                        "personalData": {
                            "view": "custom:views/record/panels/relationship"
                        }
                    }
                client/custom/src/views/record/panels/relationship.js
                Code:
                define('custom:views/record/panels/relationship', ['views/record/panels/relationship'], function (Dep) {
                
                    return Dep.extend({
                
                        afterRender: function () {
                            Dep.prototype.afterRender.call(this);
                            this.listenTo(this.nestedViews.list.collection, 'sync', function () {
                                this._parentView.reRender();
                            }, this);
                        }
                
                    });
                });
                Last edited by telecastg; 07-15-2021, 06:30 AM.

                Comment


                • Ananya K
                  Ananya K commented
                  Editing a comment
                  Error: Uncaught TypeError: Cannot read property 'collection' of undefined

                • telecastg
                  telecastg commented
                  Editing a comment
                  I can't reproduce the error, the code is working fine in our application.

                  Please post the contents of the following scripts:

                  custom Opportunity clientDefs file (Opportunity.json)

                  custom PersonalData clientDefs (PersonalData.json)

                  custom PersonalData entityDefs (PersonalData.json)

                  Also: are you using the custom client/custom/src/views/record/panels/relationship.js for any other relationships aside from Opportunity->PersonalData ?

              • #9
                espocrm/client/custom/src/views/record/panels/relationship.js

                Code:
                    afterRender: function () {
                        Dep.prototype.afterRender.call(this);
                        console.log('relationship.js afterRender() this = ',this);
                
                        this.listenTo(this.nestedViews.list.collection, 'sync', function () {
                        this._parentView.reRender();
                    }, this);
                Here, also I am getting errors. this.collection have value. But length will be null.

                Error: VM7862:29 Uncaught TypeError: Cannot read property 'collection' of undefined

                There is nothing in this.nestedViews. It is empty.
                this.collection have personalData view but the length is empty.

                Comment


                • #10
                  telecastg

                  All mentioned files are attached.

                  Also: are you using the custom client/custom/src/views/record/panels/relationship.js for any other relationships aside from Opportunity->PersonalData ?
                  - No
                  Attached Files
                  Last edited by Ananya K; 07-16-2021, 12:32 PM.

                  Comment


                  • #11
                    Hello Ananya K

                    I am trying to recreate your scenario, but need some more details:

                    Now the status of personal data gets updated
                    how exactly is this field updated. By the user editing the PersonalData entity or ?

                    If you update PersonalData and then go to Opportunity in the same machine, the relationship panel will be automatically updated, since the Opportunity detail view causes a collection of linked PersonalData to be built with the latest data in the database. There's no need for any custom code to accomplish this, but I suspect that this is not what you are looking for.

                    If you are talking about updating or creating a PersonalData in one machine and use javascript to refresh the Opportunity display in another machine without any operator action, sort of mimicking a WebSocket, the only way you can accomplish this using javascript, in my opinion, is to create a timer loop in the opportunity detail view to reRender periodically, triggering a request to the database but you will also need to have a trigger to stop the timer to avoid a forever loop.

                    The above solution of course will cause constant requests to the server and therefore usage of bandwidth, not just when PersonalData is updated anywhere.

                    I don't know enough about server setups but I guess that depending on your resources (running on a shared hosting service, having your own host, etc.) and type of setup this might or might not be an issue.

                    If you want to try this approach, here's the code that I used to implement it. This will refresh the Opportunity detail view every 10 seconds so any changes made to any linked PersonalData record will be reflected. The loop ends when the user moves to a different page.

                    custom/Espo/Custom/Resources/metadata/entityDefs/PersonalData.json
                    Code:
                    {
                        "fields": {
                            "opportunity": {
                                "type": "link"
                            }
                        },
                        "links": {
                            "opportunity": {
                                "type": "belongsTo",
                                "foreign": "proposals",
                                "entity": "Opportunity",
                                "audited": true,
                                "isCustom": true
                            }        
                        }
                    }
                    custom/Espo/Custom/Resources/metadata/clientDefs/Opportunity.json
                    Code:
                    {
                        "relationshipPanels": {
                            "proposals": {
                                "rowActionsView": "views/record/row-actions/empty",
                                "create": false,
                                "select": false,
                                "view": "custom:views/record/relationship-updatable"
                            }
                        }
                    }
                    custom/Espo/Custom/Resources/metadata/entityDefs/Opportunity.json
                    Code:
                    {
                        "fields": {
                            "proposals": {
                                "type": "linkMultiple",
                                "layoutDetailDisabled": true,
                                "layoutMassUpdateDisabled": true,
                                "noLoad": true,
                                "importDisabled": true,
                                "isCustom": true
                            }
                        },
                    
                        "links": {
                            "proposals": {
                                "type": "hasMany",
                                "foreign": "opportunity",
                                "entity": "PersonalData",
                                "audited": false,
                                "isCustom": true
                            }
                        }
                    }
                    client/custom/src/views/record/relationship-updatable.js
                    Code:
                    Espo.define('custom:views/record/relationship-updatable', 'views/record/panels/relationship', function (Dep) {
                    
                        return Dep.extend({
                    
                            afterRender: function () {
                                Dep.prototype.afterRender.call(this);
                                var originalUrl = window.location.href;
                                var self = this;
                                var timer = setInterval(function(){
                                    var newUrl = window.location.href;
                                    self._parentView._parentView.reRender();
                                    if(newUrl !== originalUrl) {
                                        clearInterval(timer);
                                    }
                                }, 10000);
                            }
                    
                        });
                    });
                    Note: I opted for implementing this mechanism in the PersonalData relationship view instead as of doing it in the Opportunity detail view to avoid unwanted reRender while a user was updating an Opportunity record. This is not an issue fir the relationship view since it is not possible for a user to update the PersonalData record while in the Opportunity detail display.
                    Last edited by telecastg; 07-19-2021, 04:54 AM. Reason: Explain why this code is not put directly in the Opportunity detail view.

                    Comment


                    • #12
                      telecastg

                      how exactly is this field updated? By the user editing the PersonalData entity or ? -> API

                      Refreshing the opportunity page every 10 sec is not a good user experience I feel.

                      On the Opportunity Details page, I have created a button to create a Personal Data entity. We will run many background API calls to create and update the created personal data entity. So, when a new entry is created I will trigger reload of opportunity. So the Relationship panel will update.

                      My personal Data list small has a status field. Now me on the Opportunity page and the personal data status is updated from API in the background. Now I want the relationship panel to update the Personal Data Status so that I will get the latest data in the opportunity datil view and relationship view without refresh.

                      This is not happening with the Socket.

                      Can I achieve this?

                      Comment


                      • #13
                        I don't think so without either user action or the loop scheme.

                        When the user creates a new Personal Data entity at the Opportunity detail display, the action triggers a server call, so the whole display is updated.

                        This has to do with the basic client server architecture, getting server information requires the client to issue a server call.

                        In the case of Espo and Backbone this is done with a brilliant use of Ajax, so only the bare minimum information is updated from the server, while most elements of user interaction are handled locally by your browser through Javascript.

                        The above gives the user a feeling of being dynamically exchanging data both ways with the server, at far better speeds than with a traditional webpage, but at the end of the day the server does not "PUSH" anything to your browser, it is your browser through Javascript commands that "PULLS" data from your server when you invoke a Javascript command.

                        If having the Personal Data info constantly updated without user interaction is essential, perhaps you could play with setting "refresh" interval less often until you achieve an acceptable balance that will not diminish the user experience.
                        Last edited by telecastg; 07-19-2021, 05:44 PM.

                        Comment


                        • #14
                          One point of caution about using a loop as described above: If the user stays in the same page for a very long period, or leaves the same page open and walks away from the computer, the browser eventually will crash because it is executing the loop until the user goes to a different page.

                          It will not affect the application or the database but it will be necessary to open a new window to run Espo again.
                          Last edited by telecastg; 07-21-2021, 03:55 PM.

                          Comment

                          Working...
                          X