Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binding with multiple values #10

Open
magda26 opened this issue Sep 12, 2018 · 10 comments
Open

Binding with multiple values #10

magda26 opened this issue Sep 12, 2018 · 10 comments

Comments

@magda26
Copy link

magda26 commented Sep 12, 2018

I´m trying to bind the selected values, but i don´t know how.
I'm using the value option in my tagfield item like this:
bind: { value : '{record.topics}', }
but in this case I had an error in this line:
var keys = Object.keys( this._selected ),
so I inserted an "If" tag before:
if( !this._selected )this._selected = {};
and in this case It didn´t throw any error but it didn't bind either.

So i don't know if it´s the correct way to implement it.

Thanks for help with this issue

@CarlosRamirez2997
Copy link

i have same problem, i need to bind selected values

@measproem
Copy link

I also have the same problem.

@magda26
Copy link
Author

magda26 commented Sep 21, 2018

Try with selected instead of value, I customized my code and it worked with other changes.

@measproem
Copy link

Try with selected instead of value, I customized my code and it worked with other changes.

Could you help provide us with your working code?

@magda26
Copy link
Author

magda26 commented Sep 21, 2018

My changes in Tagfield.js:

applyStore: function(store) {
        if (store) {
            store = Ext.data.StoreManager.lookup(store);
        }
        return store;
    },
    updateStore: function(store, oldStore) {
        if (oldStore) {
            if (oldStore.getAutoDestroy()) {
                oldStore.destroy();
            }
        }
    },
    onSelect( t, recs ) {
        let i = 0, len = recs.length;
        if( !this._selected ) {
            this._selected = [];
        }
        while( i < len ) {
            if (!this._selected.some(function(element){
                return element.id == recs[i].data.id;
            })){
                Ext.Array.include (this._selected,recs[i].data);
                this.addTag( recs[ i ].data );
            }
            i++;
        }
        this.validate();
    },

    onDeselect( t, recs ) {
        let i = 0, len = recs.length;
        while( i < len ) {
            for(var j = 0 ; j < this._selected.length; j++ ){
                if (this._selected[j].id ==  recs[ i ].id)
                this._selected.splice(j, 1);
            }
            Ext.Array.clean(this._selected);
            this.removeTag( recs[ i ]);
            i++;
        }
        this.validate();
    },
    addTag( tag ) {
        let el = document.createElement( 'span' );
        el.id = `${this.id}-tag-${tag.id}`;
        el.innerHTML = `${tag.name} <span style="margin-left: 2px; color: var( --base-foreground-color ); cursor: pointer;${ tag.preventDeselection && ' display: none;' }" class="x-fa fa-times-circle" aria-hidden="true">&nbsp;</span>`;
        el.style.padding = '4px';
        el.style.margin = '4px';
        el.style.cursor = 'default';
        el.style.backgroundColor = 'var( --base-color )';
        el.style.color = 'var( --base-foreground-color )';
        el.style.borderRadius = '3px';
        if( tag.tagCls ) {
            el.classList.add( tag.tagCls );
        }
        if( tag.color ) {
            el.style.border = `2px solid ${ tag.color }`;
        } else {
            el.style.boxShadow = '1px 1px 1px var( --base-dark-color )';
        }
        el.setAttribute( 'tagFieldSpan', true );

        el.querySelector( 'span' ).addEventListener( 'click', function() {
            this.getPicker().onItemDeselect( [ tag ] );
            this.getPicker().setItemSelection( [ tag ], false );
        }.bind( this ) );

        this.beforeInputElement.append( el );
        this.beforeInputElement.setStyle({
            marginRight: '10px',
            flexWrap: 'wrap'
        });
        // This let and its nullification seem unnecessary, but it was implied that this would aid with garbage collection
        let storedValues = this.getValue();
        this.fireEvent( 'change', this, storedValues, this._selected );
        storedValues = null;
    },
    removeTag( tag ) {
        let removed = tag.name;
        let el = this.beforeInputElement.down( `#${this.id}-tag-${tag.id}` );
        if( el ) {
            el.destroy();
        }
        if( !this.expanded ) {
            this.syncLabelPlaceholder( true );
        }

        // This let and its nullification seem unnecessary, but it was implied that this would aid with garbage collection
        let storedValues = this.getValue();
        this.fireEvent( 'change', this, storedValues, this._selected, removed );
        storedValues = null;
        removed = null;
    },

    getValue(){
        var keys = [], i = 0, values = [];
        if(this._selected instanceof Array){
            for(var i = 0 ; i < this._selected.length ; i++){
                values.push(this._selected[i].id);
            }
        }else{
            keys = Object.keys( this._selected );
            var  len = keys.length;
            while( i < len ) {
                values.push( this._selected[ keys[ i ] ].get( this.getValueField() ) );
                i++;
            }
        }
        return values;
    },
    setValue( v ) {
        let selection = [];

        if( !( v instanceof Array ) ) {
            v = [ v ];
        }
        let i = 0, len = v.length, store = this.getPicker().getStore(), f, me = this;

        if( !store ) {
            return false;
        }
        if( !store.isLoaded() ) {
            store.addListener( 'load', () => {
                me.setValue( v );
            } );
            return false;
        }

I changed the element managed to work only with "id" and "name" values because that's what I keep in my viewmodel's record .
I also added in my component the next code to add all tags that were before in my viewmodel record:
initialize: function() { this.callParent(arguments); var top = this.getViewModel().get('record').topics; if(!top){ this.getViewModel().set('record.topics', []); }else{ var tagF = Ext.ComponentQuery.query("#tagfield")[0]; if (tagF){ top .forEach(topic => { tagF.addTag(topic); }); } } }
note that I'am stored the values in record.topics.
This code still presents some errors, like this one
image
when the box is removed with the X the field doesn't change it's color.

@measproem
Copy link

@magda26 It not work for me yet, If i try with static data store like author sample it works, if store via Binding not work.

@magda26
Copy link
Author

magda26 commented Sep 21, 2018

@meashsim

  1. Do you load the store before component starts ? (Use flags to know the exact moment the store loads )
  2. Did you add the applyStore and updateStore methods in the Tagfield.js?
  3. I include all the file i´m using (with ExtJs 6.5.2 modern triton toolkit. ) if you see any difference.
    Tagfield.txt

@measproem
Copy link

@magda26 I think problem store may be. but I think store load before component start because xtype combox it works has list data. But when change to 'tagfield' no any data the i press key 's' show error.
groups

error

@measproem
Copy link

measproem commented Sep 22, 2018

@magda26 I think related bind it delay load result of data, so default empty store will be assigned, with applyStore it fine to deal with load correct data store but updateStore seem not success update current empty store that why my combobox still problem.
I don't have any idea to solve it yet.
Base on Stackoverflow but using another component type to built multi select: Stackoverflow

@measproem
Copy link

measproem commented Sep 23, 2018

This working code problem with Bind delayed
`

applyStore: function(store)

{

    if (store) {

        store = Ext.data.StoreManager.lookup(store);

		this.getPicker().setStore(store);//This line fixed bug because data with bind are delayed

    }

    return store;

},

updateStore: function(store, oldStore) {

    if (oldStore) {

        if (oldStore.getAutoDestroy()) {

            oldStore.destroy();

        }

    }

},

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants