FirebaseExtended / polymerfire

Polymer Web Components for Firebase
https://www.webcomponents.org/element/firebase/polymerfire
MIT License
459 stars 142 forks source link

Adapting firestore-mixin for lit-element #355

Open kr05 opened 6 years ago

kr05 commented 6 years ago

Description

I'm currently trying to integrate firestore-mixin into my project, and I've come across a couple of errors. For example, when the mixin tries to call this.splice it throws. I fixed that particular error by replacing this.splice with Arrray.splice, and it seems have worked...although I can't say if that's the best solution. The most recent error I've encountered is one I can't figure out how to fix, so I'm hoping I can get some suggestions here. The mixin throws when it tries to call this._createMethodObserver. Here's the relevant code, including the document I'm trying to access. I also attached a screenshot of the error.

//my-element.js
static get properties() {
    return {
        pid: String,
        patient: {
            type: Object,
            doc: 'patients/{pid}',
            live: true
        }
    }
}
//end my-element.js

//firestore-mixin.js
_firestoreBind(name, options) {
    const defaults = {
        live: false,
        observes: [],
    }
    const parsedPath = parsePath(options.doc || options.collection);
    const config = Object.assign({}, defaults, options, parsedPath);
    const type = config.type =
        config.doc ? 'doc' : config.collection ? 'collection' : undefined;
    this._firestoreProps[name] = config;
    const args = config.props.concat(config.observes);

    console.log('args:', args)

    // What can this be replaced with?
    // ----------------------------------------------------------------------
    if (args.length > 0) {
        // Create a method observer that will be called every time
        // a templatized or observed property changes
        const observer =
            `_firestoreUpdateBinding('${name}', ${args.join(',')})`
        this._createMethodObserver(observer);
    }
    // ----------------------------------------------------------------------

    this._firestoreUpdateBinding(name, ...args.map(x => this[x]));
}
//end firestore-mixin.js

image

I tried simply removing the call, but the patient property remains undefined. Any suggestions would be greatly appreciated!

Browsers Affected

Scarygami commented 6 years ago

_createMethodObserver is part of the property-effects mixin which isn't included in lit-element.

You can try including the mixin in your firestore-mixin implementation. lit-element handles the properties element quite differently from what you might be used from polymer-element though.

kr05 commented 6 years ago

After much tinkering, I was able to make it work. Any suggestions on how I can improve my solution will be greatly appreciated. Here's the updated code:


//firestore-mixin.js
_firestoreBind(name, options) {
    const defaults = {
        live: false,
        observes: [],
    }
    const parsedPath = parsePath(options.doc || options.collection);
    const config = Object.assign({}, defaults, options, parsedPath);
    const type = config.type =
        config.doc ? 'doc' : config.collection ? 'collection' : undefined;
    this._firestoreProps[name] = config;
    const args = config.props.concat(config.observes);

    if (args.length > 0) {

        //Updated code
        //-----------------------------------------------------------
        this.argsObject = {
            args: args,
            name: name
        };
        //-----------------------------------------------------------

    } else {
        this._firestoreUpdateBinding(name, ...args.map(x => this[x]));
    }
}
//end firestore-mixin.js

//my-element.js
static get properties() {
    return {
        pid: String,
        patient: {
            type: Object,
            doc: 'patients/{pid}',
            live: true
        },
        argsObject: Object
    }
}

_shouldRender(props, changedProps, prevProps) {
    console.log('should render:', changedProps);
    if(changedProps && changedProps.pid && this.argsObject) {
        var argsArr = props.argsObject.args;
        this._firestoreUpdateBinding(props.argsObject.name, ...argsArr.map(x => this[x]))
    }
    return true;
}
//end my-element.js

What I'm doing is manually setting the argsObject, which is declared in my-element. This object has the name and args properties, which are needed to call _firestoreUpdateBinding. I then added the _shouldRender method, which calls the _firestoreUpdateBinding method whenever the pid property changes. It also has some extra checks to prevent errors, such as a null check for the changedProps object and a null check for the argsObject.