Announcement

Collapse
No announcement yet.

Capturing after:save event of bottom panel link from field view

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

  • Capturing after:save event of bottom panel link from field view

    Hello,

    Scenario

    Say we have a bottom panel in detail view of Entity A. I click the edit drop-down of one of the records in the bottom panel to open the edit modal dialog window. I edit the record and click save. This closes the dialog and shows the detail view of Entity A again.

    What I'm trying to achieve

    I have a field in the detail view of Entity A. I want this field to be able to listen to the after:save event described above so I can tell it to re-render itself if any of the bottom panel records are edited and saved.

    What I've tried

    I tried adding this to a custom view of my field. But this only fires if I edit entity A's fields or click edit and then save on the detail screen. This doesn't fire when editing bottom panel records in their corresponding dialog windows.

    Code:
    setup: function () {
    
    
    Dep.prototype.setup.call(this);
    
    this.listenTo(this.model,'after:save',(model,options) => {
    console.log('afterSave');
    });
    
    },​

  • #2
    I think it can be done from the relationship panel view. You can define a custom view in clientDefs > relationshipPanels. There can have access to both the parent model, and the list view collection. Not sure, but likely there will be some event called on the collection. You can check which one by subscribing to the 'all' event.
    If you find EspoCRM good, we would greatly appreciate it if you could give the project a star on GitHub. We believe our work truly deserves more recognition. Thanks.

    Comment


    • czcpf
      czcpf commented
      Editing a comment
      Thank you so much! I will check it out.

  • #3
    Since I needed my event to fire anytime any of the bottom panel collections changed, I decided to use a dynamic-handler instead. Below is my code for that for anyone else needing something like this.


    Code:
    define('mymodule:my-dynamic-handler', 'dynamic-handler', function(Dep) {
    
        return Dep.extend({
    
            // called on initialization
            init: function() {
    
                this.recordView.listenTo(
                    this.recordView,
                    'after:render',
                    this.afterRender.bind(this)
                );
    
                //standard listener for model changes
                this.recordView.listenTo(this.model, 'after:save', (model, options) => {
                    this.refreshMyModel();
                });
            },
    
            // put things that depending on rendering inside here
            afterRender: function() {
                this.setupBottomPanelCollectionHandlers();
            },
    
            //setup listen events for all the collections
            setupBottomPanelCollectionHandlers: function() {
    
                let bottomPanelCollections = this.getBottomPanelCollections();
                for (let key in bottomPanelCollections) {
                    let collection = bottomPanelCollections[key];
    
                    //add handlers for collection changes (added, remove, changes)
    
                    //listen to the sync event once to determine when the collection is finished loading initially.
                    //otherwise, 'update' event will fire when collection is finished loading
                    this.recordView.listenToOnce(collection, 'sync', (collection, data, obj) => {
                        // event fires when models have been added, removed, changed (this includes new models which have not been saved to db, ie new rows)
                        // curiously, this event doesn't fire for existing models when you change their individual fields. for that we need the change event below
                        this.recordView.listenTo(collection, 'update', (collection, o) => {
                            this.refreshMyModel();
                        });
                        //event fires anytime something in the collection changes (this seems to include existing models only)
                        this.recordView.listenTo(collection, 'change', (model, o) => {
                            this.refreshMyModel();
                        });
    
                    });
                }
    
            },
    
            /**
             * Return a object of collections in the bottom panels
             * @return {Object<Collection>|{}}
             */
            getBottomPanelCollections: function() {
    
                let bottomPanelCollections = {};
                let bottomView = this.recordView.getView('bottom') || null;
    
                if (!bottomView) {
                    return null;
                }
    
                let bottomPanelViews = bottomView.nestedViews;
    
                for (let key in bottomPanelViews) {
                    //only add bottom panel views that have collection
                    if (!bottomPanelViews[key].collection) {
                        continue;
                    }
                    bottomPanelCollections[key] = bottomPanelViews[key].collection;
                }
    
                return bottomPanelCollections;
    
            },
    
            //this function is called when collections are saved, changed, or removed or when the model itself changes
            refreshMyModel: function() {
    
                //refresh model to update all fields
                this.model.fetch();
    
            },
    
    
        });
    });​
    ​


    Comment


    • warmspace
      warmspace commented
      Editing a comment
      Where do I save this file? What is the file name? Please write instructions.

  • #4
    Dynamic handler is discussed in the docs here

    Comment


    • #5
      I did it according to your instructions:
      PHP Code:
      define('custom:opportunity-dynamic-handler', ['dynamic-handler'], function (Dep) {

          return 
      Dep.extend({

              
      init: function () {
                  
                  
      this.recordView.listenTo(
                      
      this.recordView,
                      
      'after:render',
                      
      this.afterRender.bind(this)
                  );
                  
                   
      this.recordView.listenTo(this.model'after:save', (modeloptions) => {
                      
      this.refreshMyModel();
                  });
                  
              },        
              
              
      afterRender: function() {
                  
      this.setupBottomPanelCollectionHandlers();
              },
              
              
      setupBottomPanelCollectionHandlers: function() {

                  
      let bottomPanelCollections this.getBottomPanelCollections();
                  for (
      let key in bottomPanelCollections) {
                      
      let collection bottomPanelCollections[key];

                      
      this.recordView.listenToOnce(collection'sync', (collectiondataobj) => {
                          
      this.recordView.listenTo(collection'update', (collectiono) => {
                              
      console.log('update');
                              
      this.refreshMyModel();
                          });
                          
      this.recordView.listenTo(collection'change', (modelo) => {
                              
      console.log('change');
                              
      this.refreshMyModel();
                          });

                      });
                      
                  }

              },
              
              
      /**
               * Return a object of collections in the bottom panels
               * @return {Object<Collection>|{}}
               */
              
      getBottomPanelCollections: function() {

                  
      let bottomPanelCollections = {};
                  
      let bottomView this.recordView.getView('bottom') || null;

                  if (!
      bottomView) {
                      return 
      null;
                  }

                  
      let bottomPanelViews bottomView.nestedViews;

                  for (
      let key in bottomPanelViews) {
                      
                      if (!
      bottomPanelViews[key].collection) {
                          continue;
                      }
                      
      bottomPanelCollections[key] = bottomPanelViews[key].collection;
                  }

                  return 
      bottomPanelCollections;

              },
              
               
      refreshMyModel: function() {

                  
      this.model.fetch();

              },
              
            
          });
      });
      ​ 
      It works, but only with Main Panel. When updating data from the Bottom Panel, "update" is displayed in the console, and refreshMyModel () is executed, but the data is not updated, which changes Formula
      Code:
      cBalance = amountConverted-entity\sumRelated('cCPayments', 'valueConverted', 'Income');
      Data is changed using Formula only when the Main Panel is updated.
      What could be the problem?

      Comment


      • #6
        I think formula only fires afterSave of entity in backend, since the model is not saved, it would not be called. You could try this.model.save() instead of this.model.fetch().

        I think if you re-wrote your formula script in a readLoader this.model.fetch() may work.

        Some easier options could also be to refresh the page instead of refresh the model.​

        Comment


        • warmspace
          warmspace commented
          Editing a comment
          It helped: this.model.fetch()

        • czcpf
          czcpf commented
          Editing a comment
          Could you share your solution so others can see? What did you end up doing?

      • #7
        Originally posted by czcpf View Post
        Could you share your solution so others can see? What did you end up doing?​​
        PHP Code:
        define('custom:opportunity-dynamic-handler', ['dynamic-handler'], function (Dep) {

        return 
        Dep.extend({

        init: function () {

        this.recordView.listenTo(
        this.recordView,
        'after:render',
        this.afterRender.bind(this)
        );

        this.recordView.listenTo(this.model'after:save', (modeloptions) => {
        this.refreshMyModel();
        });

        },

        afterRender: function() {
        this.setupBottomPanelCollectionHandlers();
        },

        setupBottomPanelCollectionHandlers: function() {

        let bottomPanelCollections this.getBottomPanelCollections();
        for (
        let key in bottomPanelCollections) {
        let collection bottomPanelCollections[key];

        this.recordView.listenToOnce(collection'sync', (collectiondataobj) => {
        this.recordView.listenTo(collection'update', (collectiono) => {
        console.log('update');
        this.refreshMyModel();
        });
        this.recordView.listenTo(collection'change', (modelo) => {
        console.log('change');
        this.refreshMyModel();
        });

        });

        }

        },

        /**
        * Return a object of collections in the bottom panels
        * @return {Object<Collection>|{}}
        */
        getBottomPanelCollections: function() {

        let bottomPanelCollections = {};
        let bottomView this.recordView.getView('bottom') || null;

        if (!
        bottomView) {
        return 
        null;
        }

        let bottomPanelViews bottomView.nestedViews;

        for (
        let key in bottomPanelViews) {

        if (!
        bottomPanelViews[key].collection) {
        continue;
        }
        bottomPanelCollections[key] = bottomPanelViews[key].collection;
        }

        return 
        bottomPanelCollections;

        },

        refreshMyModel: function() {

        this.model.save()

        },


        });
        });
        ​ 

        Comment

        Working...
        X