OVERVIEW Provide a UI system that makes it easy to build and manage interfaces through messages. UIs are primarily used to show and interact with data, so the interface should be focused on making it easy to create data-focused interfaces. The system should provide the following features: - use messages to build interfaces. - interfaces can be built through improvisation (via messages). - use templates to create reusable complex interfaces - data change messages are translated to UI messages. - no need to refresh after every UI change during development - built interfaces can be exported into a config. - configs can be loaded and/or turned into templates. - PKs will be added automatically to widgets that need them. - many parts of this system can be used externally. Future things to solve - How to handle messages across multiple forms in a single app? PROBLEMS - only change parts of the data - this is a separate problem, but relates to forms. You should be able to only update a small piece of the data, say using a data.change signal and only those key/values provided are updated (instead of the whole object being resaved). - changes to UI attributes - There should be a way to completely re-write an element, or just update a single attribute. - surface.build can be used, but should include a flag attribute that signifies it's an overwrite verse an update. - form binding and processing - forms can be bound to a standard object. that is the state of the form. form has the object name, while the name atty on each form element is a key. this can be easy to modify. - multiple forms - a router cell based on some form value can be used to define where the form.submit is routed. - easy data binding - using a surface.bind element? - list binding - a list of objects can be bound to an object that is an array. this can be updated via cells, which will send the data.changed event, which will update the bound UI. - how to handle updates to containers? - an app panel has a built in title. all elements are added to it. currently, changing the title triggers an entire rebuild of the element, but it loses it's chidren along the way. how should that be handled? - there are many solutions. one is to copy it's contents. this can get messy because the elements can have a lot of nodes that will need to be compared against. can do differential analysis and only update the parts that changed. the caches could track the children and completely re-render all children. could force detethering of containers from changable data, but that doesn't solve attribute problems. SIGNALS (listens) surface.build surface.bind.data surface.bind.click surface.bind.submit data.changed SURFACE.BUILD == with templates / blueprints [done] The default path is building from a blueprint. Most widgets are built from some combination of dom elements and the templates are the blueprints for those items. Think of them like recipes for your widgets. @idea: rename template to blueprint in surface. When building, it will start by creating the spec. This is a combination of the blueprint and the input.payload. The payload defines the customizations to the template. The spec is the DNA for the widget. This spec is cached. == compiling before build [done] During the widget build process, the system will pre-compile the spec into a build object. That object, instead of the spec, is what is build. This process handles all mustache variables, loads cached data, etc. == rebuild *new Sometimes, an object may need to be re-built. The likely reason is because data that it maps to has changed. When the surface.build signal is sent with just the PK, it will build from the cached spec. == update only *new There is a common use case for changing a single or subset of properties on an object. This can be due to changes (highlighting for errors) or making modifications while building. Rebuilding from spec with a subset of payload will automatically update the spec. To completely overwrite, you will need to pass the flag "overwrite" This will reload the spec from the template and discard anything that exists in the cache. == autobind *new Each widget can be auto-bound to an object in the local datastore. This is done by passing a 'autobind' attribute in the input.payload. It will bind to a dataobject set to ui.pk, where PK is the widget's PK. If that doesn't exist, the autobind will fail. == rebuilding elements with children *new How to handle when an element is re-built that has children? An easy first option is to move all children over. This seems easy on the surface, but isn't that easy when a template has multiple children. Another option is to call build on all children. That causes some mapping issues, especially since we are mapping parents to dom elements, not their spec. This causes issues because the spec template may have children that don't exist as specs that are re-written to. DATA.CHANGED == expects bound data to exist [done] If the PK of the data object changed does not exist in the caches, no data changes should be run. == keeps a local data cache [done] There is a local cache of data. This is the data that is displayed. It is a copy of the data from the last change message it received. Any widgets that update data will first update the cache. It will be defined later when the update messages should be sent to the data store. == separate cache that maps data and widgets [done] A second cache exists that manages what widgets are matched to which pieces of data. This helps define how the elements should exist. The map cache is separate to handle cases where multiple objects may bind to the same piece of data. Instead of managing separate copies of the data, we have the single source of truth in the separate data cache. == rebuild affected widgets [done] Widgets that are mapped to changed data will rebuild when a change occurs. A single surface.build call is made with the PK of the widget. The surface.build signal will handle the rebuild process. DATA.BIND DEFINITIONS widget - any UI-based element that displays to an end user. CALL SEQUENCE build -> build_blueprint load_template compile_template bind_data cache_blueprint display get_data_from_cache build_domel build_children "get parent from blueprint" "add new or replace existing el"