Open one modal from another modal, but keep the first open

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • onepoint0
    Member
    • Jul 2023
    • 41

    Open one modal from another modal, but keep the first open

    Hi devs,

    I have an entity 'Service' which represents a technician doing a service on a camera. During a service it's possible for the tech to replace components such as a lens on the camera. I've set it up so that they can do this from a custom action on the Service as described here: https://docs.espocrm.com/development/custom-buttons/ eg:

    Click image for larger version  Name:	Screen Shot 2023-12-15 at 4.54.24 pm.png Views:	0 Size:	56.2 KB ID:	100716

    (to be clear, they would be replacing a component on the Camera SN123 - you can't see those components on this screen)

    When the custom button is clicked, it opens the lens list in a modal:

    Click image for larger version  Name:	lenslist.png Views:	0 Size:	59.9 KB ID:	100717


    When a lens is clicked in the model, the code does an ajax call and replaces the existing lens on the camera with the selected one.

    This all works fine, but I want to make the user add a reason for replacing the lens. I can successfully open a second modal from the first one, but the first modal closes behind it:

    Click image for larger version  Name:	reasonmodal.png Views:	0 Size:	50.3 KB ID:	100718

    I want to keep it open so that I can give the user the opportunity to cancel instead of entering a reason and be returned to the lens list to make another selection if they want.

    I've tried a lot of different ideas such as trying to remove the listener that is closing the first modal (I don't think it's the right approach) and extending the the record-select.js view to customise the lens list from there but I can't make those work. Here is my code:

    Code:
    define('custom:my-action-handler', ['action-handler', 'views/modal', 'model'], function (Dep, Modal, Model) {
        return Dep.extend({
            actionTest: function (data, e) {
            console.log('model = ', this.view.model);
            camName = this.view.model.get('cameraName');
    
            Espo.Ui.notify(' ... ');
    
            var viewName = this.getMetadata().get('clientDefs.Lens.modalViews.select') || 'views/modals/select-records';
    
            this.view.createView('dialog', viewName, {
                // this.view.createView('dialog', 'custom:extend-select', {
                scope: 'Lens', //scope: 'Team',
                headerText: `Replace lens on ${camName}`,
                createButton: true, //false,
                multiple: false,
                selectable: false,
                skipBuildRows: false,
             }, (view) => {
                view.render();
                Espo.Ui.notify(false);
          
                console.log('my view ', view);
    
               this.view.listenToOnce(view, 'select', models => {
                  console.log('listen view - select ', view);
                  this.secondModal();
               });
         });
      },
    
      secondModal: function () {
          this.view.createView('dialog', 'views/modal', {
          isBeingRendered: true,
          templateContent: '<p>Please enter a reason for changing the lens:</p><input id="change-lens-reason"></input>',
          headerText: 'Hello world',
          backdrop: true,
          message: 'Some *message*\n\nHello world!',
          buttonList: [
            {
              name: 'addReason',
              label: this.view.translate('Please add reason'),
              onClick: () => {
                 // call addLinkLens
                this.close();
              },
               style: 'primary',
           },
          {
            name: 'close',
            label: this.view.translate('Close'),
          }
        ],
        }, view => {
         view.render();
       });
    },
       addLinkLens: function (id, name) {
            console.log('addLinkLens - model id = ', id, ' name = ', name);
            console.log('searchData 2 ', this.view.searchData);
            // ajax call here to replace lens and create a history record with old lens
        },
        initTest: function () {
            this.controlActionVisibility();
            
            this.view.listenTo(
                this.view.model,
                'change:status',
                this.controlActionVisibility.bind(this)
        );
    },
    controlActionVisibility: function () {
    console.log('in controlActionVisibility ', this.view.model);
    },
    });
    });​
    I can see that once the lens list modal is open, if I add a search filter to the list and open the select, a second modal is opening up and leaving the first intact (eg, clicking the select in the below image), exactly how I want to do it, but I can't figure out how it is doing that:

    Click image for larger version  Name:	Screen Shot 2023-12-15 at 5.11.35 pm.png Views:	0 Size:	21.1 KB ID:	100719

    Can anyone please give me some tips on how to proceed?

    Cheers,
    Clare
    Last edited by onepoint0; 12-15-2023, 06:42 AM.
  • onepoint0
    Member
    • Jul 2023
    • 41

    #2
    I'm still trying to figure this one out. I think part of the story is that there is a listener in select-records.js in loadList that closes the modal:

    Code:
    this.listenToOnce(view, 'select', (model) => {
        console.log('listen to once select-record');
        this.trigger('select', model);
        this.close();
    });​
    If I don't open a second modal at all and comment out the this.close in the above code then my first modal doesn't close when I click on any of the records in the list (partial success).

    Unfortunately if I keep that this.close commented out and then open a second modal, it closes anyway. I have debugged it extensively and I can't figure out why that is happening. I feel like this should do what I want - keep the first modal open but also open a second modal - but obviously there is something else going on here as well.

    Additionally, If I stop listening to 'select' in the callback to createView, that listener in select-records is not running and the modal doesn't close, but then also, my listen on 'select' is gone and the second modal doesn't open:

    Code:
    this.view.createView('dialog', viewName, {
        scope: 'Lens', //scope: 'Team',
       headerText: `Replace lens on ${camName}`,
       createButton: true, //false,
       multiple: false,
       selectable: false,
       skipBuildRows: false,
    }, (view) => {
       view.render();
       Espo.Ui.notify(false);
    
       view.stopListening(view.model, 'select'); // <-- this works to stop it closing!!
    ​
       view.listenToOnce(view, 'select', models => { // <-- but this doesn't fire
          this.secondModal();
       });
    });​
    Something else I don't understand is why the listener is set up on the view, eg:

    Code:
    // in select-records.js
    this.listenToOnce(view, 'select', (model) => {
    But I can't remove it from the view, only the model:

    Code:
    // in my-action-handler.js in callback to createView
       view.stopListening(view.model, 'select'); // <-- this stops the listener firing
    ​
       view.stopListening(view, 'select'); // <-- this seems to do nothing
    ​
    ​​

    Initially I thought I could stop listening to 'select' and then reattach the listener without the this.close, but nothing I do seems to reattach the listener (maybe once I stop listening, there is no select for a new listener to listen to?).

    I've tried extending select-records and detaching the listener in both setup and loadList (loadList is where the listener is in select-records). I think this is because I don't have access to the model here and I need to stop listening on the model :

    Code:
    setup: function () {
       Dep.prototype.setup.call(this);
       console.log('in setup extend-select ', this);
    
       this.stopListening(this.model, 'select'); // <-- try to detach on model - this doesn't work and I don't have access to the model (this.model = undefined)
    
       this.stopListening(this, 'select'); // <-- try to detach on view - doesn't work
    ​
       this.listenToOnce(this, 'select', (model) => { // this fires but not if I successfully remove the listener in the callback to my-action-handler createView
          console.log('listen to once extend-select');
          this.trigger('select', model);
       });
    },
    
    loadList: function () {
       Dep.prototype.loadList.call(this);
       console.log('load list - this is ', this);
       this.stopListening(this, 'select'); // <-- doesn't work :(
    },​
    I guess I don't understand the scope of these listeners. If anyone has any thoughts on how I could achieve this I would be grateful!​
    Last edited by onepoint0; 12-20-2023, 06:28 PM.

    Comment

    Working...