Skip to content

Instantly share code, notes, and snippets.

@davideast
Last active February 8, 2019 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davideast/fe9cf78ce9ef741d13178d085c45cad3 to your computer and use it in GitHub Desktop.
Save davideast/fe9cf78ce9ef741d13178d085c45cad3 to your computer and use it in GitHub Desktop.
syncWithElements
// https://stackblitz.com/edit/typescript-h68plq?file=index.ts
import firebase from 'firebase/app';
import 'firebase/firestore';
import { syncWithElements } from './sync';
const app = firebase.initializeApp({ projectId: "alwaysbecaching" });
const unsub = syncWithElements(app, {
parent: document.querySelector('.container'),
collectionName: 'boxes',
classList: ['box'],
config: {
id: 'id',
text: 'innerText',
bg: 'style.backgroundColor',
color: 'style.color'
},
events: ['added', 'modified']
});
// 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment