<Doc>: No difference between "Loading" and "Doesn't Exist"
<script>
/**
* @type {string}
*/
export let entry;
import { doc, setDoc } from 'firebase/firestore';
import { SignedIn, SignedOut, Doc } from 'sveltefire';
import { firestore } from '$lib/firebase'; // your firestore instance
let editingNote = false;
let newNote = '';
function editNote(n) {
editingNote = true;
newNote = n;
}
async function saveNote(id) {
editingNote = false;
// set doc in firestore to newNote data
await setDoc(doc(firestore, 'words', id), {
note: newNote
});
}
</script>
{entry}
<Doc ref={`words/${entry}`} let:data>
{#if !editingNote && data?.note === undefined}
<SignedIn>
<button on:click={editNote(data?.note)}>Add Note</button>
</SignedIn>
{:else if !editingNote}
<p>{data?.note}</p>
<SignedIn>
<button on:click={editNote(data?.note)}>{data?.note ? 'Edit Note' : 'Add Note'}</button>
</SignedIn>
{:else if editingNote}
<form on:submit|preventDefault={saveNote(entry)}>
<textarea bind:value={newNote} />
<button type="submit">Save</button>
<button type="reset" on:click={() => (editingNote = false)}>Cancel</button>
</form>
{/if}
<p slot="loading">Loading...</p>
</Doc>
I can't get this to continue beyond the loading state despite everything else working. This component is Note.svelte and it is instantiated within the context of a <FirebaseApp> so everything else is available.
Without the log option, I can't see what's wrong with the Doc component.
I turned off ssr in the svelte config as well:
import adapter from '@sveltejs/adapter-auto';
/** @type {import('@sveltejs/kit').Config} */
const config = {
ssr: false,
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter()
}
};
export default config;
What is going wrong?
Nothing in console as well btw
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// This rule allows anyone with your Firestore database reference to view, edit,
// and delete all data in your Firestore database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your Firestore database will be denied.
//
// Make sure to write security rules for your app before that time, or else
// all client requests to your Firestore database will be denied until you Update
// your rules
match /{document=**} {
allow read: if true;
allow write: if request.auth.uid != null;
}
}
}
the firestore rules allow authenticated writes and I definitely can read. I am signed in on my app as well
Ok so specifically, there's no way to tell if a Document is just not there, or if it's still loading since the loading slot is triggered in both cases.
I'm making a dictionary app where you can take notes on words, and those words are in a collection called "words" and they are located at words/{word}
I would like to have the ability to do
<Doc ref={`words/${word}`} let:data>
{data.note}
<div slot="no-data">
<button>Add data</button>
</div>
<div slot="loading">
Loading
</div>
</div>
{#if data == undefined} hi {/if}
I tried every permutation of these but I don't think anything like this will work because only the loading state is shown if there's no data
<script lang="ts" generics="Data extends DocumentData">
import type {
DocumentData,
DocumentReference,
Firestore,
} from "firebase/firestore";
import { docStore } from "../stores/firestore.js";
import { getFirebaseContext } from "../stores/sdk.js";
export let ref: string | DocumentReference<Data>;
export let startWith: Data | undefined = undefined;
const { firestore } = getFirebaseContext();
let store = docStore(firestore!, ref, startWith);
interface $$Slots {
default: {
data: Data;
ref: DocumentReference<Data> | null;
firestore?: Firestore;
};
loading: {};
}
</script>
{#if $store !== undefined && $store !== null}
<slot data={$store} ref={store.ref} {firestore} />
{:else}
<slot name="loading" />
{/if}
I tried a few other things
<script>
const post = docStore(firestore, `words/${entry}`);
console.log(post);
console.log($post);
let docSnap;
onMount(async () => {
docSnap = await getDoc(doc(firestore, `words/${entry}`));
});
</script>
....
<div slot="loading">
{#if docSnap && docSnap.exists()}
exists
{:else}
doesn't exist
{/if}
{#if $post == undefined}
hi
{:else}
loading...
{/if}
</div>
exists() returns after a second true or false so maybe we could have <Doc> have the following behavior
Loading exists() comes back false -> Doesn't-Exist exists() comes back true -> Shows Content
<script>
/**
* @type {string}
*/
export let entry;
import { doc, getDoc, setDoc } from 'firebase/firestore';
import { SignedIn, SignedOut, Doc, docStore } from 'sveltefire';
import { firestore } from '$lib/firebase'; // your firestore instance
import { onMount } from 'svelte';
let editingNote = false;
let newNote = '';
function editNote(n) {
editingNote = true;
newNote = n;
}
async function saveNote(id) {
editingNote = false;
// set doc in firestore to newNote data
await setDoc(doc(firestore, 'words', id), {
note: newNote
});
}
const post = docStore(firestore, `words/${entry}`);
console.log(post);
console.log($post);
let docSnap;
onMount(async () => {
docSnap = await getDoc(doc(firestore, `words/${entry}`));
});
let exists = true;
$: exists = docSnap && docSnap.exists();
</script>
<Doc ref={`words/${entry}`} let:data let:ref>
{#if !editingNote}
<p>{data?.note}</p>
<SignedIn>
<button on:click={editNote(data?.note)}>{data?.note ? 'Edit Note' : 'Add Note'}</button>
</SignedIn>
{:else if editingNote}
<form on:submit|preventDefault={saveNote(entry)}>
<textarea bind:value={newNote} />
<button type="submit">Save</button>
<button type="reset" on:click={() => (editingNote = false)}>Cancel</button>
</form>
{/if}
<div slot="loading">
{#if exists}
<span>Loading</span>
{:else}
<SignedIn>
<form on:submit|preventDefault={saveNote(entry)}>
<textarea bind:value={newNote} />
<button type="submit">Add Note</button>
<button type="reset" on:click={() => (editingNote = false)}>Cancel</button>
</form>
</SignedIn>
{/if}
</div>
</Doc>
I ended up having to do this; sort of buggy and annoying though
https://github.com/codediodeio/sveltefire/issues/96
i'll drop a pr for this