1. #1
    Sencha User
    Join Date
    Dec 2012
    Posts
    13
    Vote Rating
    0
    noncom is on a distinguished road

      0  

    Default Answered: A modal window to edit a particular field in a Grid

    Answered: A modal window to edit a particular field in a Grid


    I have a grid which displays records. A record represents an object that has an attribute which is a list of strings. In the record, I want only the number of these strings (the list's length) to be on display. However, I also would like to make it so that if a user clicks on the field, a modal window opens which allows to edit all these strings, so that they be updated and sent via AJAX back to the server.

    For now I have a fully-working grid with records that are taken from the server and are sent back on editing, except for that particuar fields which is required to be treated in a special way.

    My best guess on how to make the field display a number of strings instead of the array that contains them - is to use a 'converter' for the value?

    How can I acheive all this with ExtJS?

  2. When you show the window use update() to update the html in the window.
    However, using that just updates the raw HTML in the window. If you were to add components like Ext form fields you'd use add() / remove() / removeAll().

    Not sure why listeners shows as null and I think the i's are just placeholders of some sort to indicate that the value is a complex object. Try in Firebug and it'll look a little different, but give the same information.

  3. #2
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    5,080
    Answers
    398
    Vote Rating
    186
    slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold

      0  

    Default


    I'd use a renderer function on the column and point the column's dataindex to the field with the array / string data (wasn't totally sure what that looked like for you).

    Here's an example that uses the renderer and I used a cell editor to allow the user to edit the underlying value. That could be a popup window instead, too, but thought I'd demo this in case it met your needs within the grid real estate.

    Code:
    Ext.create('Ext.data.Store', {
        storeId:'simpsonsStore',
        fields:['list'],
        data:[{
            list: '1, 2, 3'
        }]
    });
    
    
    Ext.create('Ext.grid.Panel', {
        title: 'Simpsons',
        store: Ext.data.StoreManager.lookup('simpsonsStore'),
        plugins: 'cellediting',
        columns: [{
            text: 'List',
            dataIndex: 'list',
            flex: 1,
            renderer: function (val) {
                return val.split(',').length;
            },
            editor: {
                xtype: 'textfield'
            }
        }],
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
    });
    Last edited by slemmon; 13 Mar 2013 at 7:29 AM. Reason: wrap code in code tags

  4. #3
    Sencha User
    Join Date
    Dec 2012
    Posts
    13
    Vote Rating
    0
    noncom is on a distinguished road

      0  

    Default


    I have the values in an array.

    JSON:
    Code:
    {..., scoring: [{points:2, interval: [[0, 0],[5, 30]]}, {points:10, interval: [[5,30],[15,45]]},... ], ...}
    the "scoring" is the array of objects. So I want to print the length of "scoring" to the grid and enable editing the objects through the pop-up model window.

    I have been able to adapt your example for my case. It really shows the number of items in the array, however, when I click on the cell, it fills itself with "[object Object] [object Object] ..." stuff and after I stop editing the cell, the count becomes the count of the characters in the string... that is no good.

    So, the mission is partly accomplished, but I would like to make a model window popup with all the dields editable. Say, I know how to do it partly, but what is unclear to me:

    1) How to make a window popup upon clicking the cell?
    2) How to get access to the array of objects (so that I could generate the input elements of the window)?
    3) How to tie back the input from the window to the original object so that I could update it, updating it on the server (just as if it would happen in case of simple editing)?

  5. #4
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    5,080
    Answers
    398
    Vote Rating
    186
    slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold

      0  

    Default


    Does the below code give you some good jumping off points?

    A window component is created and associated to the grid. When a row/item is double-clicked the window is passed the record of the row clicked then shown. The window has a show listener that could be used to populate the form with fields depending on what is in the record's scoring field.

    When you save information form the form in the modal window just save back directly to the myRecord record instance associated to your edit window. The record will then have new data an you can sync()/autoSync it back to the server.

    Code:
    Ext.create('Ext.data.Store', {
        storeId:'simpsonsStore',
        fields:['scoring'],
        data:[{
            scoring: [{points:2, interval: [[0, 0],[5, 30]]}, {points:10, interval: [[5,30],[15,45]]} ]
        }]
    });
    
    
    
    
    Ext.create('Ext.grid.Panel', {
        title: 'Simpsons',
        store: Ext.data.StoreManager.lookup('simpsonsStore'),
        myWindow: Ext.widget('window', {
            modal: true
            , height: 200
            , width: 200
            , layout: 'fit'
            , html: 'Have the window host a form that you populate with fields using the scoring data from the record passed in to the window when it is shown'
            , closeAction: 'hide'
            // , listeners: { show: function (w) { create your record editing form using the data from w.myRecord.get('scoring') } }
        }),
        columns: [{
            text: 'Scoring',
            dataIndex: 'scoring',
            flex: 1,
            renderer: function (val) {
                return val.length;
            }
        }],
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
        , listeners: {
            itemdblclick: function (view, record) {
                var myWindow = view.ownerCt.myWindow;
                myWindow.myRecord = record;
                myWindow.show();
            }
            , destroy: function (g) { Ext.destroy(g.myWindow); }
        }
    });

  6. #5
    Sencha User
    Join Date
    Dec 2012
    Posts
    13
    Vote Rating
    0
    noncom is on a distinguished road

      0  

    Default


    Very good! This code helps me to do what I need. For now I have been able to adapt it to my case and everything works. I did not implement the actual form generation inside the window yet, I think, I'll do it on monday and will report on how it works.

    Meanwhile, I have some more side-questions. Here is my adapted code:

    Code:
    var var_grid = Ext.widget({
        editWindow: Ext.widget('window', {
            listeners: {
                show: function (w) {
                    console.log('window = ' + w); /*w.html = 'test successful';*/
                }
            },
            height: 200,
            layout: 'fit',
            closeAction: 'hide',
            width: 200,
            modal: true
        }),
        columns: [{
            text: 'Name',
            sortable: true,
            dataIndex: 'name',
            width: 200
        }, {
            text: 'Description',
            sortable: false,
            dataIndex: 'description',
            width: 75
        }, {
            text: 'Scoring',
            renderer: function (val) {
                console.log(val + '  len = ' + val.length);
                return val.length;
            },
            sortable: true,
            editor: {
                xtype: 'window'
            },
            dataIndex: 'scoring',
            width: 100
        }, {
            text: 'Twitter',
            sortable: true,
            dataIndex: 'twitter',
            width: 100
        }],
        store: store,
        name: 'grid',
        listeners: {
            itemdblclick: function (view, record) {
                var editWindow = view.ownerCt.editWindow;
                editWindow.myRecord = record;
                editWindow.html = 'ahahaha';
                editWindow.show();
            },
            destroy: function (g) {
                Ext.destroy(g.editWindow);
            }
    
    
        },
        xtype: 'gridpanel'
    });
    What is unclear to me:
    1) Why it works showing "ahahaha", but does not work to show "test successful"? (assuming if I uncomment it). Without this working I will not be able to insert the form there..?
    2) The window object, printed out by the "show" listener is as follows (unrelated parts removed):

    i {listeners: null, height: 200, layout: i, closeAction: "hide", width: 200…}
    • items: i
    • keyMap: i
    • lastBox: Object
    • layout: i
    • listeners: null
    • myRecord: i
    a) I assume listeners is null here because they're not yet initialized while printing this out, rigtht?
    b) What is the "i" thing that is allover the printout?

    Sry, those might be JS issues, not ExtJS, but I am new to both of them, so I hope these questions
    make sense.

  7. #6
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    5,080
    Answers
    398
    Vote Rating
    186
    slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold

      0  

    Default


    When you show the window use update() to update the html in the window.
    However, using that just updates the raw HTML in the window. If you were to add components like Ext form fields you'd use add() / remove() / removeAll().

    Not sure why listeners shows as null and I think the i's are just placeholders of some sort to indicate that the value is a complex object. Try in Firebug and it'll look a little different, but give the same information.

  8. #7
    Sencha User
    Join Date
    Dec 2012
    Posts
    13
    Vote Rating
    0
    noncom is on a distinguished road

      0  

    Default


    Sorry, I've been ill and away from work for these days.. now I am continuing with the task.

    Alright, I have almost succeeded with all of it. I am creating the window and receiving AJAX object from the server to populate the window. However, one more problem there is. I have tried two ways to put the form into the window. First one was with "win.update()" and it populated the form with text, which is good for debug so that I know that the AJAX object is received and intact. The output is this:

    Ext.widget({ items: [ { fieldLabel: 'name', name: 'name', xtype: 'textfield' } , { fieldLabel: 'description', name: 'description', xtype: 'textfield' } , { fieldLabel: 'scoring[0]', name: 'scoring[0]', xtype: 'textfield' } , { fieldLabel: 'scoring[1]', name: 'scoring[1]', xtype: 'textfield' } , { fieldLabel: 'scoring[2]', name: 'scoring[2]', xtype: 'textfield' } , { fieldLabel: 'maxPerDay', name: 'maxPerDay', xtype: 'textfield' } , { fieldLabel: 'twitter', name: 'twitter', xtype: 'textfield' } ] , url: '/create/activity', name: 'activity', buttons: [ { text: 'Reset', handler: function(){ this.up('form').getForm().reset();} , name: 'btn_reset_activity' } , { text: 'Submit', handler: function(){ if(this.up('form').getForm().isValid()){ this.up('form').getForm().submit()} } , name: 'btn_submit_activity' } ] , layout: 'form', width: 300, xtype: 'form' } );

    and that means all is ok. But! When I use "win.add()" to really add he form to the window, it remains blank and the following message is in the console. Seems like it is the last obstacle .. can't find any info on the net about that though.. (((
    • [COLOR=red !important]Uncaught TypeError: Cannot read property 'floating' of undefined ext-all.js:38[/COLOR]
      • [COLOR=red !important]Ext.define.add[/COLOR]ext-all.js:38
      • [COLOR=red !important]Ext.Ajax.request.success[/COLOR]activity:142
      • [COLOR=red !important]Ext.apply.callback[/COLOR]ext-all.js:38
      • [COLOR=red !important]Ext.define.onComplete[/COLOR]ext-all.js:38
      • [COLOR=red !important]Ext.define.onStateChange[/COLOR]ext-all.js:38
      • [COLOR=red !important](anonymous function)



        [/COLOR]

  9. #8
    Sencha User
    Join Date
    Dec 2012
    Posts
    13
    Vote Rating
    0
    noncom is on a distinguished road

      0  

    Default


    While trying to understand the problem, I have replaced the production version of "ext.js" with the development one, and the error message has more info now, but it does not help me to understand what is the problem anyway... Here it is:
    Code:
    
    
    Object
    
    • msg: "Cannot add null item to Container with itemId/id: window-1009"
    • sourceClass: "Ext.container.AbstractContainer"
    • sourceMethod: "add"
    • __proto__: Object
      • __defineGetter__: function __defineGetter__() { [native code] }
      • __defineSetter__: function __defineSetter__() { [native code] }
      • __lookupGetter__: function __lookupGetter__() { [native code] }
      • __lookupSetter__: function __lookupSetter__() { [native code] }
      • constructor: function Object() { [native code] }
      • hasOwnProperty: function hasOwnProperty() { [native code] }
      • isPrototypeOf: function isPrototypeOf() { [native code] }
      • propertyIsEnumerable: function propertyIsEnumerable() { [native code] }
      • toLocaleString: function toLocaleString() { [native code] }
      • toString: function toString() { [native code] }
      • valueOf: function valueOf() { [native code] }
    ext-all.js:11380
    • [COLOR=red !important]Uncaught Ext.container.AbstractContainer.add(): Cannot add null item to Container with itemId/id: window-1009 ext-all.js:10528[/COLOR]
      • [COLOR=red !important]Ext.Error.Ext.extend.statics.raise[/COLOR]ext-all.js:10528
      • [COLOR=red !important]Ext.define.add[/COLOR]ext-all.js:45395
      • [COLOR=red !important]Ext.Ajax.request.success[/COLOR]activity:142
      • [COLOR=red !important]Ext.apply.callback[/COLOR]ext-all.js:11182
      • [COLOR=red !important]Ext.define.onComplete[/COLOR]ext-all.js:36228
      • [COLOR=red !important]Ext.define.onStateChange[/COLOR]ext-all.js:36176
      • [COLOR=red !important](anonymous function)[/COLOR]
    It says it cannot add "null" item, which I do not understand why, since the form is not null, this was proved by printing it out to the window... Any idea on what that means?

Thread Participants: 1

Tags for this Thread