// https://stackblitz.com/edit/typescript-h68plq?file=sync.ts import { sortedChanges, snapToData, collectionChanges } from 'rxfire/firestore'; import { map } from 'rxjs/operators'; export function syncDOM(element, config, values) { for (let key in values) { if (values.hasOwnProperty(key)) { const mapped = config[key]; if (mapped) { if (mapped.indexOf('style.') !== -1) { let style = mapped.replace('style.', ''); element.style[style] = values[key] } else { element[mapped] = values[key]; } } } } } export function syncWithElements(app, { collectionName, parent, classList, config, events = ['added', 'removed', 'modified'] as firebase.firestore.DocumentChangeType[] }) { const ref = app.firestore().collection(collectionName); const idMap = config.id || 'id'; const sub = collectionChanges(ref, events).pipe( map(changes => changes.map(c => ({ type: c.type, ...snapToData(c.doc, idMap) })) as any[]) ).subscribe(records => { records.forEach(record => { switch (record.type) { case 'added': { // TODO: Find a way to template the element const element = document.createElement('div'); element.classList.add(...classList); syncDOM(element, config, record) parent.appendChild(element); break; } case 'modified': { const element = document.getElementById(record[idMap]); syncDOM(element, config, record) break; } case 'removed': { const element = document.getElementById(record[idMap]); element.remove(); break; } } }); }); return sub.unsubscribe; }