Form component now supports edit recprd

This commit is contained in:
Michael Shanks 2020-07-07 20:16:03 +01:00
parent 671170d564
commit 9208a43cf1
5 changed files with 113 additions and 22 deletions

View File

@ -1,5 +1,5 @@
import regexparam from "regexparam"
import { routerStore } from "../state/store"
import { appStore } from "../state/store"
import { getAppId } from "./getAppId"
export const screenRouter = ({ screens, onScreenSelected, window }) => {
@ -49,7 +49,7 @@ export const screenRouter = ({ screens, onScreenSelected, window }) => {
})
}
routerStore.update(state => {
appStore.update(state => {
state["##routeParams"] = params
return state
})

View File

@ -8,6 +8,7 @@ export const bbFactory = ({
store,
componentLibraries,
onScreenSlotRendered,
getCurrentState,
}) => {
const apiCall = method => (url, body) => {
return fetch(url, {
@ -53,6 +54,8 @@ export const bbFactory = ({
store: store,
api,
parent,
// these parameters are populated by screenRouter
routeParams: () => getCurrentState()["##routeParams"],
}
}
}

View File

@ -26,8 +26,14 @@ export const createStateManager = ({
routeTo,
}) => {
let handlerTypes = eventHandlers(routeTo)
let currentState
// creating a reference to the current state
// this avoids doing store.get() ... which is expensive on
// hot paths, according to the svelte docs.
// the state object reference never changes (although it's internals do)
// so this should work fine for us
let currentState
appStore.subscribe(s => (currentState = s))
const getCurrentState = () => currentState
const bb = bbFactory({

View File

@ -13,14 +13,14 @@
number: "number",
}
let newModel = {
modelId: model,
}
let record
let store = _bb.store
let schema = {}
let modelDef = {}
let saved = false
let saving = false
let recordId
let isNew = true
let inputElements = {}
@ -30,6 +30,8 @@
$: fields = Object.keys(schema)
$: Object.values(inputElements).length && setForm(record)
async function fetchModel() {
const FETCH_MODEL_URL = `/api/models/${model}`
const response = await _bb.api.get(FETCH_MODEL_URL)
@ -42,7 +44,8 @@
if (saving) return
saving = true
const SAVE_RECORD_URL = `/api/${model}/records`
const response = await _bb.api.post(SAVE_RECORD_URL, newModel)
const response = await _bb.api.post(SAVE_RECORD_URL, record)
const json = await response.json()
if (response.status === 200) {
@ -51,7 +54,13 @@
return state
})
resetForm()
// wipe form, if new record, otherwise update
// model to get new _rev
if (isNew) {
resetForm()
} else {
record = json
}
// set saved, and unset after 1 second
// i.e. make the success notifier appear, then disappear again after time
@ -72,29 +81,58 @@
el.checked = false
}
}
newModel = {
record = {
modelId: model
}
}
const setForm = rec => {
if (isNew || !rec) return
for (let fieldName in inputElements) {
if (typeof rec[fieldName] === "boolean") {
inputElements[fieldName].checked = rec[fieldName]
} else {
inputElements[fieldName].value = rec[fieldName]
}
}
}
const handleInput = field => event => {
let value
if (event.target.type === "checkbox") {
value = event.target.checked
newModel[field] = value
record[field] = value
return
}
if (event.target.type === "number") {
value = parseInt(event.target.value)
newModel[field] = value
record[field] = value
return
}
value = event.target.value
newModel[field] = value
record[field] = value
}
onMount(() => {
const routeParams = _bb.routeParams()
recordId = Object.keys(routeParams).length > 0 && (routeParams.id || routeParams[0])
isNew = !recordId || recordId === "new"
if (isNew) {
record = { modelId: model }
} else {
const GET_RECORD_URL = `/api/${model}/records/${recordId}`
_bb.api.get(GET_RECORD_URL)
.then(response => response.json())
.then(rec => {
record = rec
setForm(rec)
})
}
});
</script>
<form class="form" on:submit|preventDefault>

View File

@ -13,33 +13,39 @@
number: "number",
}
let newModel = {
modelId: model,
}
let record
let store = _bb.store
let schema = {}
let modelDef = {}
let saved = false
let saving = false
let recordId
let isNew = true
let inputElements = {}
$: if (model && model.length !== 0) {
fetchModel()
}
$: fields = Object.keys(schema)
$: Object.values(inputElements).length && setForm(record)
async function fetchModel() {
const FETCH_MODEL_URL = `/api/models/${model}`
const response = await _bb.api.get(FETCH_MODEL_URL)
modelDef = await response.json()
schema = modelDef.schema
}
async function save() {
// prevent double clicking firing multiple requests
if (saving) return
saving = true
const SAVE_RECORD_URL = `/api/${model}/records`
const response = await _bb.api.post(SAVE_RECORD_URL, newModel)
const response = await _bb.api.post(SAVE_RECORD_URL, record)
const json = await response.json()
if (response.status === 200) {
@ -48,7 +54,13 @@
return state
})
resetForm()
// wipe form, if new record, otherwise update
// model to get new _rev
if (isNew) {
resetForm()
} else {
record = json
}
// set saved, and unset after 1 second
// i.e. make the success notifier appear, then disappear again after time
@ -69,26 +81,58 @@
el.checked = false
}
}
newModel = {
record = {
modelId: model
}
}
const setForm = rec => {
if (isNew || !rec) return
for (let fieldName in inputElements) {
if (typeof rec[fieldName] === "boolean") {
inputElements[fieldName].checked = rec[fieldName]
} else {
inputElements[fieldName].value = rec[fieldName]
}
}
}
const handleInput = field => event => {
let value
if (event.target.type === "checkbox") {
value = event.target.checked
newModel[field] = value
record[field] = value
return
}
if (event.target.type === "number") {
value = parseInt(event.target.value)
newModel[field] = value
record[field] = value
return
}
value = event.target.value
newModel[field] = value
record[field] = value
}
onMount(() => {
const routeParams = _bb.routeParams()
recordId = Object.keys(routeParams).length > 0 && (routeParams.id || routeParams[0])
isNew = !recordId || recordId === "new"
if (isNew) {
record = { modelId: model }
} else {
const GET_RECORD_URL = `/api/${model}/records/${recordId}`
_bb.api.get(GET_RECORD_URL)
.then(response => response.json())
.then(rec => {
record = rec
setForm(rec)
})
}
});
</script>
<form class="form" on:submit|preventDefault>