Hybrid View

  1. #1
    Sencha User
    Join Date
    Feb 2011
    Posts
    74
    Vote Rating
    3
    shaneavery is on a distinguished road

      1  

    Smile New "Multi-select field" extension for ST2 (RC)

    New "Multi-select field" extension for ST2 (RC)


    I created a new class that extends/overrides Select.js in a minimalistic way to provide a basic "Multi-select" field. It is based on Mitchell Simoens' concepts for his ST 1.1 multi-select field. The component stores the selected items as a comma separated string in the text field portion of itself. It uses a "List" dataview panel to provide a GUI for multiple selection of values. Other than that, it behaves identically to a "Select" field. It is designed to be added to an MVC folder structure, since I don't really consider it a "real" extension at this point. It has been tested in ST2 RC, and it seems to be working well so far. The code is below:

    Form field item definition (add this to your "Form Panel" config, note the xtype):

    Code:
                        {
                            xtype        : 'multiselectfield',
                            name         : 'Tags',
                            label        : 'Tags',
                            store        : 'Tags',
                            displayField : 'text', //don't change this property
                            valueField   : 'value', //don't change this property
                            usePicker    : false //required
                        }
    Multiselect class (create a file called "MultiSelect.js" and put it in your "app/view/" folder - then paste in this code - modify as necessary):

    Code:
    Ext.define('app.view.MultiSelect', {
        extend: 'Ext.field.Select',
        alias : 'widget.multiselectfield',
        xtype : 'multiselectfield',
        usePicker : false,  //force list panel, not picker
    
        getTabletPicker: function() {  //override with modified function
            var config = this.getDefaultTabletPickerConfig();
            if (!this.listPanel) {
                this.listPanel = Ext.create('Ext.Panel', Ext.apply({
                    centered: true,
                    modal: true,
                    cls: Ext.baseCSSPrefix + 'select-overlay',
                    layout: 'fit',
                    hideOnMaskTap: false,
                    items: {
                        xtype: 'list',
                        mode: 'MULTI', //set list to multi-select mode
                        store: this.getStore(),
                        itemTpl: '<span class="x-list-label">{' + this.getDisplayField() + '}</span>',
                        listeners: {
                            select : this.onListSelect,
                            itemtap  : this.onListTap,
                            hide : this.onListHide, //new listener
                            scope  : this
                        },
                        items: { //new button to trigger formatting/setting new field value with joined string
                            xtype: 'button',
                            text: 'Done',
                            ui: 'action',
                            height: '20px',
                            width: '50%',
                            docked: 'bottom',
                            style: 'margin-top: 10px; margin-bottom: 10px; margin-left: auto; margin-right: auto;',
                            listeners: {
                                tap: this.onButtonTap,
                                scope: this
                            }
                        }
                    }
                }, config));
            }
            return this.listPanel;
        },
        
        applyValue: function(value) {  //override with modified function
            var record = value,
                index;
            this.getOptions();
            if (!(value instanceof Ext.data.Model)) {
                index = this.getStore().find(this.getValueField(), value, null, null, null, true);
    
                if (index == -1) {
                    index = this.getStore().find(this.getDisplayField(), value, null, null, null, true);
                }
                //We do not want to get record from store //record = this.getStore().getAt(index);
                 this.element.dom.lastChild.firstChild.firstChild.value = value; //display csv string in field when value applied
            }
            return record;
        },
    
        updateValue: function(newValue, oldValue) {  //override with modified function
            this.previousRecord = oldValue;
            this.record = newValue;
            // String does not have methods //this.callParent([newValue ? newValue.get(this.getDisplayField()) : '']);
            this.fireEvent('change', this, newValue, oldValue);
        },
    
        getValue: function() {  //override with modified function
            var record = this.record;
            return (record) // Use literal string value of field // ? record.get(this.getValueField()) : null;
        },
    
        showPicker: function() {  //override with modified function
            //check if the store is empty, if it is, return
            if (this.getStore().getCount() === 0) {
                return;
            }
            if (this.getReadOnly()) {
                return;
            }
            this.isFocused = true;
            //hide the keyboard
            //the causes https://sencha.jira.com/browse/TOUCH-1679
            // Ext.Viewport.hideKeyboard();
            if (this.getUsePicker()) {
                var picker = this.getPhonePicker(),
                    name   = this.getName(),
                    value  = {};
    
                value[name] = this.record.get(this.getValueField());
                picker.setValue(value);
                if (!picker.getParent()) {
                    Ext.Viewport.add(picker);
                }
                picker.show();
            } else { //reworked code to split csv string into array and select correct list items
                var listPanel = this.getTabletPicker(),
                    list = listPanel.down('list'),
                    store = list.getStore(),
                    itemStringArray = new Array(),
                    values = this.getValue().split(','),
                    v = 0,
                    vNum = values.length;
                if (!listPanel.getParent()) {
                    Ext.Viewport.add(listPanel);
                }
                for (; v < vNum; v++) {
                    itemStringArray.push(values[v]);
                }
                v = 0;
                for (; v < vNum; v++) {
                    var record = store.findRecord(this.getDisplayField(), itemStringArray[v], 0, true, false, false );
                    list.select(record, true, false);
                }
                listPanel.showBy(this.getComponent());
                listPanel.down('list').show();
            }
        },
    
        onListSelect: function(item, record) {  //override with empty function
        },
    
        onListTap: function() {  //override with empty function
        },
    
        onButtonTap: function() {
            this.setValue('');
            this.listPanel.down('list').hide(); //force list hide event
            this.listPanel.hide({
                type : 'fade',
                out  : true,
                scope: this
            });
        },
    
        onListHide: function(cmp, opts) {
            var me = this,
                recordArray = this.listPanel.down('list').selected.items,
                itemStringArray = new Array(),
                v = 0,
                vNum = recordArray.length;
            for (; v < vNum; v++) {
                var value = this.getDisplayField();
                itemStringArray.push(recordArray[v].data.value);
            }
            if (itemStringArray.length > 0) {
                me.setValue(itemStringArray.join(','));
                this.listPanel.down('list').deselectAll();
            } else {
                me.setValue('None');
            }
        }
    });
    I am sure there are some things that may be better optimized in the code, but this is at least functional and tested. Hope this proves useful to whomever may need it until ST2 comes with its own Multi-select field. Let me know what you think. If there is an interest, I may post it on GitHub at a later date.

    Cheers!

    Sencha Fiddle Live Test:

    Last edited by mitchellsimoens; 8 Oct 2013 at 4:32 AM. Reason: Upgraded to RC1

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    35,704
    Vote Rating
    750
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Two things, you have an id set on the list which is bad for an extension. What if someone uses that id in their app or has two of these fields? They would conflict. Other thing is you should put this up on GitHub so that people can fork it and do pull requests to make it better.
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha User
    Join Date
    Feb 2011
    Posts
    74
    Vote Rating
    3
    shaneavery is on a distinguished road

      0  

    Thumbs up Good points, thanks Mitchell...

    Good points, thanks Mitchell...


    I updated the code above to eliminate the id property and the dependance I unnecessarily created for it. I intend to post a GitHub link to this project on this thread as soon as I get a few more comments. This is my first stab at an extension, so I want a little more initial input in order to update this code before I call this an "official" extension. Your advice is a good start.

    Thanks.

  4. #4
    Sencha Premium Member
    Join Date
    Dec 2011
    Posts
    13
    Vote Rating
    1
    DodgyDave is on a distinguished road

      0  

    Default


    There's a couple of hard-coded references to the displayfield 'text'. These should be changed to this.getDisplayField().

    Code:
    var record = store.findRecord('text', itemStringArray[v], 0, true, false, false );
    
    itemStringArray.push(recordArray[v].data.text);

  5. #5
    Sencha User
    Join Date
    Feb 2011
    Posts
    74
    Vote Rating
    3
    shaneavery is on a distinguished road

      0  

    Thumbs up Thanks DodgyDave...

    Thanks DodgyDave...


    I updated the code above to reflect your corrections. Nice catch. This is the kind of constructive criticism I am looking for.

    Thanks.

  6. #6
    Sencha User
    Join Date
    Feb 2011
    Posts
    74
    Vote Rating
    3
    shaneavery is on a distinguished road

      0  

    Exclamation Updated for ST2 RC

    Updated for ST2 RC


    FYI...

    I upgraded the code to fix a bug for the RC release. This code will not work for Beta3 anymore.

  7. #7
    Sencha User
    Join Date
    Aug 2013
    Posts
    3
    Vote Rating
    0
    darpan214 is on a distinguished road

      0  

    Default


    Well, I got this problem. But now, when I use Store instead of Options shown in Sencha Fiddle, It did not work. So, How can I link this field with my store? I already add configs like Store :'mystore_id', displayField :' column name' , valueField : 'column_name' (i.e. id). But Still, It is not working.Thanks in advance. I got stuck here for 20 days. Please reply.

  8. #8
    Sencha Premium Member vadimv's Avatar
    Join Date
    Sep 2010
    Location
    Chisinau, Moldova
    Posts
    647
    Vote Rating
    25
    vadimv will become famous soon enough vadimv will become famous soon enough

      0  

    Default


    Quote Originally Posted by darpan214 View Post
    Well, I got this problem. But now, when I use Store instead of Options shown in Sencha Fiddle, It did not work. So, How can I link this field with my store? I already add configs like Store :'mystore_id', displayField :' column name' , valueField : 'column_name' (i.e. id). But Still, It is not working.Thanks in advance. I got stuck here for 20 days. Please reply.
    "store" config works like to any ST component. Pls post your store code and widget's configuration.

  9. #9
    Sencha User
    Join Date
    Aug 2013
    Posts
    3
    Vote Rating
    0
    darpan214 is on a distinguished road

      0  

    Default Solved the issue for View - Now how to get values of selected items

    Solved the issue for View - Now how to get values of selected items


    Yes. I got it now. Actually I forgot to call new xtype in my view.
    Now, I want to get the values of selected items from MultiSelect xtype. I saw multiselect.js file in which there are couple of functions that look like useful for my issue. But I am not pretty sure. Can someone help me how to get array of values (as we can select multiple items through this xtype) onTapButton event?
    here is the whole structure.

    #STORE :
    Ext.define('MyApp.store.Sstudents', {
    extend: 'Ext.data.Store',
    alias: 'store.Sstudents',


    requires: [
    'MyApp.model.Mstudents'
    ],


    config: {
    autoLoad: true,
    autoSync: true,
    model: 'MyApp.model.Mstudents',
    storeId: 'Sstudents',
    proxy: {
    type: 'sql',
    table: 'CITT_STUDENTS'
    }
    }
    });

    #Model:
    Ext.define('MyApp.model.Mstudents', {
    extend: 'Ext.data.Model',


    requires: [
    'MyApp.model.Mtags'
    ],
    uses: [
    'MyApp.model.Mtags'
    ],


    config: {
    fields: [
    {
    name: 'id',
    type: 'int'
    },
    {
    name: 'fname',
    type: 'string'
    },
    {
    name: 'lname',
    type: 'string'
    }
    ],
    proxy: {
    type: 'sql',
    table: 'CITT_Students'
    },
    hasMany: {
    associationKey: 'tags',
    model: 'MyApp.model.Mtags',
    autoLoad: true,
    autoSync: true,
    foreignKey: 'id',
    name: 'tags'
    }
    }
    });

    View file #StudentPanel:
    Ext.define('MyApp.view.StudentPanel', {
    extend: 'Ext.form.Panel',
    alias: 'widget.studentpanel',


    config: {
    items: [
    {
    xtype: 'fieldset',
    itemId: 'createstudent',
    title: 'Create Student',
    items: [
    {
    xtype: 'textfield',
    label: 'First Name:',
    name: 'fname'
    },
    {
    xtype: 'textfield',
    label: 'Last Name:',
    name: 'lname'
    },
    {
    xtype: 'label',
    html: 'List of tags',
    margin: '5 5 5 10',
    ui: 'dark'
    }
    ]
    },
    {
    xtype : 'multiselectfield',
    name : 'Tag_list',
    label : 'Tags_Lists',
    store : 'Stags',
    displayField : 'title', //don't change this property
    valueField : 'id', //don't change this property
    usePicker : false //required
    },
    {
    xtype: 'button',
    itemId: 'create',
    margin: 20,
    ui: 'confirm-round',
    text: 'Create'
    }
    ]
    }


    });

    #Controller:
    Ext.define('MyApp.controller.CStudents', {
    extend: 'Ext.app.Controller',


    config: {
    refs: {
    studentsNavView: 'studentsNavView',
    studentpanel: 'studentpanel #createstudent'
    },


    control: {
    "button#students": {
    tap: 'onStudentsTap'
    },
    "list#Students": {
    itemswipe: 'onStudentsItemSwipe',
    itemtap: 'onStudentsItemTouchend'
    },
    "button#create": {
    tap: 'onCreateTap'
    },
    "button#createstudent": {
    tap: 'onCreatestudentTap'
    }
    }
    },


    onStudentsTap: function(button, e, eOpts) {
    //alert('Button taped!!!');
    Ext.Viewport.setActiveItem({xtype: 'studentsNavView'});
    },


    onStudentsItemSwipe: function(dataview, index, target, record, e, eOpts) {
    Ext.Msg.confirm("Confirmation","Are you sure you want to delete?",
    function(buttontext){
    if(buttontext == 'yes') {
    Ext.getStore('Sstudents').remove(record);
    }
    }
    );
    },


    onCreateTap: function(button, e, eOpts) {
    //alert('Saved!!!');
    // I want to get the values of each of the fields from StudentPanel View. However, I get the values for Fname and Lname. But what about Tags_Lists that has used Multiselect xtype?
    // Build up the model's data
    var fields = this.getStudentpanel().getFieldsAsArray();
    console.log('+------------------');
    var data = {};

    Ext.each(fields, function(field) {
    var key = field.getName(),
    value = field.getValue();
    data[key] = value;
    });
    console.log('*************DATA*************', data);

    // Save the model's data
    var studentsNavView = this.getStudentsNavView();
    var record = studentsNavView.getRecord();

    console.log('Record is ::', record);

    var store = Ext.getStore('Sstudents');

    if (record) {
    console.log('Inside If loop');
    record.set(data);
    studentsNavView.setRecord(null);
    } else {
    console.log('Else loop');
    store.add(data);
    }
    store.sort();

    // Navigate back to list
    this.getStudentsNavView().pop();
    },


    onStudentsItemTouchend: function(dataview, index, target, record, e, eOpts) {
    //alert('Tapped!!!');
    console.log('Edit function Called!!!');

    console.log('Selected record is ::',record);

    var studentsNavView = this.getStudentsNavView();
    console.log('Comes..!!!');

    // Navigate to student
    studentsNavView.push({
    xtype: 'studentpanel',
    title: 'Edit Student'
    }).setRecord(record);

    // save for persistance
    studentsNavView.setRecord(record);

    //tagsnavView.setRecord(record);

    console.log('studentsNavView');
    console.log(studentsNavView);

    console.log('should not come.');

    /*var taskFormField = this.getTaskFormField(),
    fields = taskFormField.getFieldsAsArray();


    Ext.each(fields, function(field) {
    var key = field.getName(),
    value = record.get(key);
    console.log('Name of Key is ::', key);
    console.log('Value is ::', value);
    field.setValue(value);
    });*/
    //mainView

    this.holdSelect = true;

    },


    onCreatestudentTap: function(button, e, eOpts) {

    // Navigate to form
    this.getStudentsNavView().push({
    xtype: 'studentpanel',
    title: 'Add Student'
    });

    //this.getAddButton().hide();
    //this.getDeleteButton().hide();

    }


    });

    Let me know if you want other than that.
    Thanks in advance. Now , I am learning Sench Touch. So, there might be couple of simple things that I dont know. Please help me.

    Darpan

  10. #10
    Sencha User
    Join Date
    Apr 2013
    Posts
    19
    Vote Rating
    0
    Ant0nin is on a distinguished road

      0  

    Default


    Hello Sencha Touch community,

    I've made a derived class of the extension. However the list values do not appear in the field, but they appear in the list at the time of the selection.

    Code:
    Ext.define('DocuTouch.form.field.ListeMulti', {
        extend: 'Ext.ux.field.MultiSelect',
        xtype: 'fieldrecherchelistemulti',
        
        constructor: function(champ) {
            
            this.callParent();
            
            var storeListe = champ.valeursListe();
            storeListe.load();
            this.setStore(storeListe);
            
            this.setName(champ.get('id'));
            this.setLabel(champ.get('nom'));
        },
        
        config: {
    
    
            // private
            pickerCanShow: true,
            
            mode: 'MULTI',
            delimiter: ", ",
            displayField: 'valeur',
            valueField: 'id',
            autoSelect: false,
            usePicker: false,
            clearIcon: true,
            value: null,
    
    
            listeners: {
                clearicontap: function(field) {
                    field.setValue(null);
                    field.setPickerCanShow(false);
                    return false;
                }
            }
        },
                
        // override
        onButtonTap: function() {
            var records = this.listPanel.down('list').getSelection();
            this.setValue(records);
            this.superclass.onListTap.call(this);
            
            if(records.length > 0) {
                this.showClearIcon();
            }
        },
                
        // override
        showPicker: function() {
            if(this.getPickerCanShow()) {
                this.callParent();
                this.setPickerCanShow(false);
            }
            else
                this.setPickerCanShow(true);
        }
    
    
    });
    Thanks in advance for help.

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar