Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    autoChildren as Window items

    I'm creating a FormDialog class, subclassing isc.Window. It's body should contain two components: a form and a button. I'm trying to use auto children. I now have this:

    Code:
    isc.defineClass('FormDialog', isc.Window).addProperties({
        formConstructor: null, // should be set when instantiating the dialog
        formDefaults: {
            autoParent: 'none',
            width: '100%'
        },
        saveButtonConstructor: 'Button',
        saveButtonDefaults: {
            autoParent: 'none',
            // submits the form
            click: function () {
                this.creator.form.submit();
            },
            title: 'Save',
            width: '100%'
        },
    
        initWidget: function () {
            // is it possible to "set" this differently?
            this.addAutoChild('form', { dataSource: this.dataSource });
            this.Super('initWidget', arguments);
        },
    
        items: ['autoChild:form', 'autoChild:saveButton'],
        ...
    });
    
    var dialog = isc.FormDialog.create({
        formConstructor: 'CustomerForm',
        dataSource: isc.CustomersDataSource.create()
    });
    Questions I have is:
    - Is the items array correct? Or can I have these auto children created differently (I've tried "addAsChild" in the formDefaults and saveButtonDefaults, but this didn't work)
    - Do I need the initWidget code so that I can pass the data source of the dialog itself to the "form" auto child?
    - Will the items be destroyed correctly when the dialog itself is destroyed?

    #2
    Setting "items" with "autoChild:" prefixes means that you would *not* call addAutoChild() for the same AutoChildren (or you'll get double creation).

    You can't use the "items" approach in your case since you want to pass through dynamic properties (like "dataSource").

    You probably want these autoChildren added to the Window's "body" AutoChild, not as direct children of the Window itself. So:

    1. you need to specify the body as the parent when calling addAutoChild(), or use createAutoChildren instead then addItem()

    2. you don't want to try to add the autoChildren before the body is created, so doing things before superclass initWidget() runs is definitely wrong

    3. addAsChild would not do the right thing

    Comment


      #3
      Thanks for the reply. If I understand correctly, this should work (apparently it doesn't):

      Code:
      isc.defineClass('FormDialog', isc.Window).addProperties({
          formConstructor: null, // should be set when instantiating the dialog
          formDefaults: { autoParent: 'body', ... },
          saveButtonConstructor: 'Button',
          saveButtonDefaults: { autoParent: 'body', ... },
      
          initWidget: function () {
              this.Super('initWidget', arguments);
              this.addAutoChild('form', { dataSource: this.dataSource });
              this.addAutoChild('saveButton');
          },
          ...
      });
      
      var dialog = isc.FormDialog.create({
          formConstructor: 'CustomerForm',
          dataSource: isc.CustomersDataSource.create()
      });
      Tried to use this.addItem(this.createAutoChild('form', { dataSource: this.dataSource }); as well, but then I'm missing the this.form instance variable which I need somewhere else in my code.

      Comment


        #4
        I made it work by replacing initWidget() with makeBody(). Not sure it this is correct behavior, but it seems to be working fine.

        Comment


          #5
          makeBody() is not documented, so that's a bad approach.

          The Window doesn't document when it creates its "body" AutoChild. Currently, it happens to do so at draw, which is why your code doesn't work (tries to add to "body" too early).

          However, even if you switched the timing so your AutoChildren were created after draw(), you would still be adding children directly to the body without going through addItem() - so basically circumventing the normal use of the widget.

          So, the most robust approach, which doesn't depend on the timing of the creation of the built-in "body" AutoChild, and only uses documented approaches, is the one previously mentioned: use createAutoChild() and addItem().

          Comment


            #6
            It seems to be working now:

            Code:
            isc.defineClass('FormDialog', isc.Window).addProperties({
                formConstructor: null, // should be set when instantiating the dialog
                formDefaults: { ... }, // no autoParent
                saveButtonConstructor: 'Button',
                saveButtonDefaults: { ... }, // no autoParent
            
                initWidget: function () {
                    this.Super('initWidget', arguments);
                    this.form = this.createAutoChild('form', { dataSource: this.dataSource }); // need a reference
                    this.addItem(this.form);
                    this.addItem(this.createAutoChild('saveButton'));
                },
                ...
            });
            
            var dialog = isc.FormDialog.create({
                formConstructor: 'CustomerForm',
                dataSource: isc.CustomersDataSource.create()
            });
            The only thing I don't like is the part that I have to set this.form myself, which addAutoChild already does. Is it possible to use that?

            Comment


              #7
              Code:
                  initWidget: function () {
                      this.Super('initWidget', arguments);
                      this.addItem(this.addAutoChild('form', { dataSource: this.dataSource }));
                      this.addItem(this.createAutoChild('saveButton'));
                  }
              });
              works!

              Comment


                #8
                Still wrong. This latest code adds the form as a direct child of the Window, then removes it and re-adds it as a child of the body.

                Again the approach we just described is the right one. You can set this.form by simply assigning to it.

                Comment


                  #9
                  So it should be this:

                  Code:
                  initWidget: function () {
                      this.Super('initWidget', arguments);
                      this.form = this.createAutoChild('form', { dataSource: this.dataSource }); // need a reference
                      this.addItem(this.form);
                      this.addItem(this.createAutoChild('saveButton'));
                  }
                  If not, please specify the solution, else we keep bouncing over and over...

                  Comment


                    #10
                    Yes, that's correct usage, doesn't rely on internals, and doesn't do extra work.

                    Comment

                    Working...
                    X