saasufy-components
v7.14.0
Published
Components for Saasufy.
Downloads
519
Readme
Saasufy Components
Components for Saasufy
Application state
Collections of resources
Single resources
User input
Authentication
Display groups
Modal windows
Overview
Many Saasufy components use a combination of <template slot="item">
and <div slot="viewport">
. Both of these are known as slotted
elements.
A <template slot="item">
is an inert/hidden element which the component uses to format its output. The <div slot="viewport">
is an element which will contain the rendered output of the component.
Components which follow this pattern take templates as input and render them inside the specified <div slot="viewport">
element. Note that the viewport can be any element and not necessarily a div
.
The most important thing to remember is that the element marked with the slot="item"
attribute serves as a template for your component and the element marked with slot="viewport"
serves as a container for its output. Although the item
slot is commonly used, components may require different slot names for input templates so it's important to read the documentation carefully.
A component's output consists of instances of your template after they've been populated with data from the component.
You can apply custom CSS/styling to elements that are rendered inside a viewport - It may be useful to add a custom class
attribute to your viewport element to allow targeting using CSS selectors.
How to use
Components
To use a component, you just need to include the relevant <script>
tag into the <head>
tag of your .html
file.
You can simply copy-paste the script tag provided under the Import
section of the relevant component's documentation.
Make sure that you read the documentation carefully; especially the list of available attributes and acceptable values for each component.
You should only add the script tags for the components which your page uses to avoid wasting bandwidth and unnecessarily delaying page load for your users.
You should always include the socket.js
script and create a top-level socket-provider
component if you intend to use components which depend on data from Saasufy.
Linking the scripts directly from saasufy.com
is the simplest way to get started as it doesn't require loading anything or hosting the scripts yourself.
An alternative approach is to download Saasufy components using npm install saasufy-components
and self-host them.
Styling
This project does not impose any specific approach to styling components, however, it comes with an optional styles.css
stylesheet which can be added inside your <head>
tag like this:
<link href="https://saasufy.com/node_modules/saasufy-components/styles.css" rel="stylesheet" />
Utility functions
The following utility functions can be used anywhere inside template {{expression}}
placeholders:
- Generate a unique random ID in UUID format:
{{uuid.v4()}}
- Generate a deterministic ID in UUID-compatible format derived from one or more values:
{{computeId('value1', 'value2')}}
- Convert text to a format suitable for use inside a URL:
{{url('This is a test')}}
- Convert text to lower case:
{{lowerCase('TEST')}}
- Convert text to upper case:
{{upperCase('test')}}
- Convert first letter of text to upper case:
{{capitalize('test')}}
- Remove leading and trailing spaces from text:
{{trim(' test ')}}
- Specify one or more fallback values in case values are null or undefined:
{{fallback(Product.imageSrc, 'path/to/default-image.png')}}
- Format UNIX timestamp as a human-readable date:
{{date(Product.updatedAt)}}
- Make a string safe by escaping HTML characters:
{{safeString(Product.name)}}
- Given an array of objects, extract the values from the specified field and join them together into a single comma-separated string:
{{joinFields(Product, 'name')}}
Special fields
Saasufy supports a number of special metadata fields which are automatically created and updated on each model record. Those fields are hidden by default but may be exposed via the Saasufy control panel and used within your application. The fields are:
id
: String, UUID v4 format; the ID of the resource.createdBy
: String, UUID v4 format; if the socket was authenticated, this will hold the ID of the account which created the resource.updatedBy
: String, UUID v4 format; if the socket was authenticated, this will hold the ID of the account which last modified the resource.createdByIp
: String, IP address format; the IP address of the client which last modified the resource.createdAt
: Number, UNIX timestamp format; the timestamp for when the resource was created.updatedAt
: Number, UNIX timestamp format; the timestamp for when the resource was last modified.
All of the above fields except for the id
field are hidden by default and must be exposed via the Saasufy control panel in order to be accessible within your front end application.
To expose a special field on a specific model, you just need to create a field with the same name under the fields
section of the relevant model.
You will need to make sure that the type you specify (String
or Number
) matches the type of the special field described above.
You will need to deploy your Saasufy service from the dashboard for the changes to take effect.
The id
field in Saasufy is extra special; you can optionally specify it when you create a new resource, however, if it is not specified, Saasufy will create one for you.
Saasufy offers utility functions for creating IDs (random and deterministic). See the previous Utility functions
section.
File hosting
Saasufy provides basic HTTP/HTTPS file hosting functionality with support for client-side caching (with ETag
).
This is especially useful for hosting images.
To upload files to Saasufy, you first need to create a field of type string
on a model of your choice.
You will then need to check/enable the blob
constraint to tell Saasufy to treat this field as a base64 file.
After you've deployed your schema from the Saasufy dashboard, you will be able to manually add new records into your model via its data
section.
Saasufy will show you a file picker next to the relevant field name which you can use to upload a file/image to Saasufy.
After adding a record to Saasufy which holds a file in one of its fields, that file can be accessed over HTTP/HTTPS via your Saasufy service's /files
HTTP endpoint.
The format of the URL to link directly to a specific file/image is:
https://saasufy.com/:serviceId/files/:modelName/:modelId/:fieldName
For example, if the URL for your Saasufy service (which you get after deploying your service) is wss://saasufy.com/sid7999/socketcluster/
and your file is stored inside an Image
model with ID 58f2051c-14bc-4518-8816-ff387cfdd57e
inside a data
field, you will be able to link to your image directly using this URL:
https://saasufy.com/sid7999/files/Image/58f2051c-14bc-4518-8816-ff387cfdd57e/data
You can use it to embed images into your application using the <img>
tag like this:
<img src="https://saasufy.com/sid7999/files/Image/58f2051c-14bc-4518-8816-ff387cfdd57e/data" alt="My image" />
Saasufy enforces access controls for HTTP in the same way as it does for its WebSocket protocol.
It's possible to block or restrict access to specific files stored on specific fields via the Access
page under the relevant model.
If your model field's access is set to restrict
, only authenticated users with matching permissions will be able to view/download the image/file.
In this case, you will need to add your user's JWT token to a cookie with the name socketcluster.saasufyService.authToken
and it will be passed along with the request.
Components
app-router
A component which allows you build apps which have multiple pages. Inside it, you should specify a template for each page in your app along with the route/path to bind each page to. This component also supports simple redirects as well as redirects based on the user's current authentication state. Redirects can be soft or hard; a soft redirect does not change the current URL/path, a hard redirect does.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/app-router.js" type="module" defer></script>
Example usage
<app-router>
<template slot="page" route-path="/:productName">
<div class="product-title">Product: {{capitalize(productName)}}</div>
</template>
<div slot="viewport"></div>
</app-router>
This example shows how an infinite number of pages can be represented with a single route template.
In this case, the /:productName
inside the route-path
attribute of the slotted <template slot="page">
element serves as a placeholder variable which can match any text.
You can then use such route variables inside the page template itself as shown with <div class="product-title">Product: {{capitalize(productName)}}</div>
- In this case, the productName
variable which comes from the route path is first capitalized using the capitalize
utility function before it is rendered into the template.
Note that the app-router
can contain any number of pages/routes so the slot="page"
attribute can be re-used multiple times, e.g:
<app-router>
<template slot="page" route-path="/home">
<div>This is the home page</div>
</template>
<template slot="page" route-path="/about-us">
<div>This is the about-us page</div>
</template>
<template slot="page" route-path="/products">
<div>This is the products page</div>
</template>
<div slot="viewport"></div>
</app-router>
This example shows how to redirect based on the user's authentication status:
<app-router default-page="/home">
<template slot="page" route-path="/log-in" auth-redirect="/home" hard-redirect>
<log-in-form
hostname="sas.saasufy.com"
port="443"
network-symbol="sas"
chain-module-name="sas_chain"
secure="true"
></log-in-form>
</template>
<template slot="page" route-path="/home" no-auth-redirect="/log-in">
<div>This is the home page</div>
</template>
<div slot="viewport"></div>
</app-router>
Note that the app router path is based on location.hash
so the path section in your browser's address bar needs to start with the #
character.
So for example, if your index.html
file is served up from the URL http://mywebsite.com
, then, to activate the /products
route as in the example above, you would need to type the URL http://mywebsite.com#/products
.
Also note that the app router will only render once its viewport
has been added and slotted into it.
If you want to make sure that some data (e.g. a config file) has been fully loaded before rendering the app, you could set the slot="viewport"
attribute on your viewport element at a later time using JavaScript.
Attributes of app-router
default-page
: The path/route of the default page to send the user to in case no routes are matched. Commonly used to point to a/page-not-found
page. For the home page, it's typically recommended to create a page template withroute-path=""
instead.debounce-delay
: The number of milliseconds to wait before changing the route. This can help to avoid multiple renders if the route changes rapidly (e.g. when doing hard redirects). Defaults to 100ms.target-page
: A convenience attribute which can be used to programmatically change thelocation.hash
in the address bar.force-render-paths
: An optional list of comma-separated paths to force a page render/re-render, regardless of whether or not the page has changed.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
Attributes of slotted page templates
route-path
: The path of the page. Supports custom URL parameters in the format/org/:orgId/user/:userId
.partial-route
: An optional attribute which, if specified, will allow theroute-path
to be matched partially from the start. This can be used to ignore the ending of a path which is not relevant to the page in order to avoid unnecessary re-renders.redirect
: An optional path/route which this page should redirect to. Note that the content of this page will not be shown so it should always be empty.no-auth-redirect
: An optional alternative path/route to redirect to if the user is on this page but they are not authenticated. If the user is authenticated, then the content of the template will be displayed as normal.auth-redirect
: An optional alternative path/route to redirect to if the user is on this page but they are already authenticated. If the user is not authenticated, then the content of the template will be displayed as normal.hard-redirect
: An optional, additional attribute which can be specified alongside aredirect
,no-auth-redirect
orauth-redirect
attribute to ensure that any redirect will change the URL in the address bar. Redirects aresoft
redirects by default; this means that they redirect the user to the target page but keep the current URL path unchanged.auto-reset-window-scroll
: If this attribute is present, the page scroll will be reset to the top when each new page is rendered.
socket-provider
A top level component which connects to your Saasufy service and inside which you can place other components which depends on Saasufy data.
A Saasufy component which integrates with data from Saasufy is known as a socket-consumer
and must always be placed inside a socket-provider
element (although it does not have to be a direct child).
Import
<script src="https://saasufy.com/node_modules/saasufy-components/socket.js" type="module" defer></script>
Example usage
<socket-provider url="wss://saasufy.com/sid7890/socketcluster/">
<!-- Elements which rely on Saasufy data go here. -->
</socket-provider>
Attributes
url
(required): Specifies the URL for the Saasufy service to use as the data store for all components which are placed inside it.auth-token-name
: Allows you to specify a custom key for your token - This will be used as the key in localStorage. You generally do not need to set this attribute. It is intended for situations were an app has multiplesocket-provider
elements connecting different services with different/separate authentication flows.disable-tab-sync
: By default, the socket provider synchronizes socket auth state across multiple tabs via localStorage. If this attribute is set, then the socket auth state will not sync automatically and a manual page refresh may be necessary to update to the latest auth state.socket-options
: Can be used to set options on the innersocket
. Must be in the formatoption1:type1=value1,option2:type2=value2
; the type of each option can be string, boolean or number. If not specified, the default type is string.disconnect-on-deauth
: If this attribute is set, the underlying socket will be disconnected if the socket becomes unauthenticated. This means that components will not receive real-time updates until the user's next interaction (which will cause the socket to reconnect). If this attribute is not set, the socket will attempt to reconnect immediately after losing authentication.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
collection-viewer
Used for rendering collections as lists, tables or other sequences based on a specific view using a template. Supports pagination by allowing you to specify custom buttons or links to navigate between pages. Can also perform basic CRUD operations such as deleting or creating records by listening for events from child components.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/collection-viewer.js" type="module" defer></script>
Example usage
<collection-viewer
collection-type="Chat"
collection-fields="username,message,createdAt"
collection-view="recentView"
collection-view-params=""
collection-page-size="50"
>
<template slot="item">
<div>
<div>{{Chat.username}}</div>
<div>{{Chat.message}}</div>
<div>{{date(Chat.createdAt)}}</div>
</div>
</template>
<template slot="no-item">
<div>There are no messages.</div>
</template>
<template slot="loader">
<div class="loading-spinner-container">
<div class="spinning">↻</div>
</div>
</template>
<div slot="viewport" class="chat-viewport"></div>
</collection-viewer>
In addition to the slots shown above, the collection-viewer
also supports the following optional slots:
previous-page
: This is typically aninput
element of typebutton
for pagination.next-page
: This is typically aninput
element of typebutton
for pagination.page-number
: This is typically adiv
element to display the current page number. Alternatively, it can be aninput-provider
element to allow the user to manually type in the page number.first-item
: This should be atemplate
element. It can be used to inject an element just above the first record. This can be useful to render thecollection-viewer
as a table with a heading above table rows.last-item
: This should be atemplate
element. It can be used to inject an element just after the last record.error
: This can be used to display an error message if the required data cannot be loaded. TheError
object can be accessed inside the template via the syntax:$CollectionName.error
(substituteCollectionName
with yourcollection-type
or, if set, yourtype-alias
preceded by a dollar sign). For example, the error message for aChat
collection will be$Chat.error.message
.
Attributes
collection-type
(required): Specifies the type of collection to display. This should match aModel
available in your Saasufy service.collection-fields
(required): A comma-separated list of fields from theModel
that you want to display or use. This lets you pick specific pieces of data from your collection to work with.collection-view
(required): Determines the view of the collection. This should match one of theViews
defined in your Saasufy service under that specificModel
.collection-view-params
(required): Parameters for the view, specified as comma-separated key-value pairs (e.g., key1=value1,key2=value2). These parameters can customize the behavior of the collection view. The keys must matchparamFields
specified in your Saasufy service under the relevantView
.collection-page-size
: Sets how many items from the collection are displayed at once. This is useful for pagination, allowing users to navigate through large sets of data in chunks.collection-page-offset
: Indicates the current page offset in the collection's data. It’s like telling the viewer which page of data you want to display initially.collection-get-count
: If this attribute is present, the component will get the record count of the target view. The count can be rendered into the template by prefixing the model name with a dollar sign and accessing thecount
property like this:{{$MyModelName.count}}
.collection-view-primary-fields
: An optional list of field names to specify which specificcollection-view-params
to watch for realtime updates. Fewer primary fields means that the view will be exposed to a broader range of realtime updates but at the cost of performance. It is generally recommended to have just one primary field.collection-disable-realtime
: If this attribute is present, the underlying collection will not listen for changes nor update in realtime. Fields of records that are in view may still update in realtime.auto-reset-page-offset
: If this attribute is present, thecollection-page-offset
will be reset to zero whenever the view params change.type-alias
: Allows you to provide an alternative name for yourModel
to use when injecting values inside the template. This is useful for situations where you may have multiplecollection-viewer
elements and/ormodel-viewer
elements of the same type nested inside each other and want to avoidModel
name clashes in the nested template definitions. For example, if thetype-alias
in the snippet above was set toSubChat
, then{{Chat.message}}
would become{{SubChat.message}}
.hide-error-logs
: A flag which, when present, suppresses error logs from being printed to the console.max-show-loader
: If this attribute is present, your slottedloader
element will be shown as often as possible; this includes situations where the collection is merely refreshing itself. It is disabled by default.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
collection-adder
A basic form component for inserting data into collections.
This component is a simplified version of the collection-adder-form
component as it doesn't require input elements to be slotted into it.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/collection-adder.js" type="module" defer></script>
Example usage
<collection-adder
collection-type="Product"
collection-fields="name,brand,qty"
model-values="categoryName=electronics,isNew:boolean=true"
submit-button-label="Create"
trim-spaces
></collection-adder>
Attributes
collection-type
(required): Specifies the type of collection to add the resource to when the form is submitted. This should match aModel
available in your Saasufy service.collection-fields
: A comma-separated list of fields from theModel
to display as input elements inside the form for the user to fill in. Each field name in this list can optionally be followed by an input element type after a:
character. For examplecollection-fields="qty:number, size:select(small,medium,large)
will create one input element withtype="number"
and one withtype=select
with optionssmall
,medium
orlarge
. To make a select field optional, you can prefix the list of options with a comma; e.g.size:select(,small,medium,large)
. Supported input types include:text
,select
,number
,checkbox
,radio
,textarea
,file
andtext-select
.model-values
: An optional list of key-value pairs in the formatfield1=value1,field2=value2
to add to the newly created resource alongside the values collected from the user via the form. For non-string values, the type should be provided in the formatfieldName:type=value
; supported types arestring
,number
andboolean
. Unlikecollection-fields
which are rendered as input elements in the form,model-values
are not shown to the user.field-labels
: Allows you to specify custom input labels by mapping field names to more user-friendly labels in the formatfieldName1='Field Name 1',fieldName2='Field Name 2'
.submit-button-label
: Text to display on the submit button. If not specified, defaults toSubmit
.hide-submit-button
: Adding this attribute will hide the submit button from the form.success-message
: A message to show the user if the resource has been successfully added to the collection after submitting the form.autocapitalize
: Can be set tooff
to disable auto-capitalization of the first input character on mobile devices.autocorrect
: Can be set tooff
to disable auto-correction of input on mobile devices.trim-spaces
: If this attribute exists on the element, then leading and trailing spaces will be trimmed from each input element's value before submitting the form.consumers
: This allows you to connect thiscollection-adder
to other elements on your page. It should be used in conjunction with theprovider-template
attribute. Theconsumers
attribute takes a list of selectors with optional attributes to target in the formatelement-selector:attribute-name
. For example.my-input:value
will find all elements with amy-input
class and update theirvalue
attributes with the output of thecollection-adder
component on submit. You can specify multiple selectors separated by commas such as.my-input,my-div
; in this case, because attribute names are not specified, values will be injected into thevalue
attribute (for input elements) or into theinnerHTML
property (for other kinds of elements). The default attribute/property depends on the element type.success-consumers
: Same as theconsumers
attribute but the target elements are only updated if insertion was a success.error-consumers
: Same as theconsumers
attribute but the target elements are only updated if insertion was a failure.provider-template
: A template string within which the{{value}}
can be injected before passing to consumers. In the case of thecollection-adder
component, the value is an object with either aresource
property (on successful insert) orerror
(on failure). On success, theresource
object will be the object which was added to the collection. On failure, theerror
object will be a JavaScriptError
object with amessage
property.
collection-adder-form
A flexible form component for inserting data into collections.
This component is similar to the collection-adder
component except that it requires input elements (and others) to be slotted into it.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/collection-adder-form.js" type="module" defer></script>
Example usage
<collection-adder-form
collection-type="Product"
model-values="categoryName=electronics,isNew:boolean=true"
trim-spaces
>
<div slot="message"></div>
<input type="text" name="name" placeholder="Name">
<input type="text" name="brand" placeholder="Brand">
<input type="number" name="qty" placeholder="Quantity">
<input type="submit" value="Add new product">
</collection-adder-form>
Attributes of collection-adder-form
collection-type
(required): Specifies the type of collection to add the resource to when the form is submitted. This should match aModel
available in your Saasufy service.model-values
: An optional list of key-value pairs in the formatfield1=value1,field2=value2
to add to the newly created resource alongside the values collected from the user via the form. For non-string values, the type should be provided in the formatfieldName:type=value
; supported types arestring
,number
andboolean
. Unlikecollection-fields
which are rendered as input elements in the form,model-values
are not shown to the user.success-message
: A message to show the user if the resource has been successfully added to the collection after submitting the form.trim-spaces
: If this attribute exists on the element, then leading and trailing spaces will be trimmed from each input element's value before submitting the form.auto-reset-hidden-inputs
: If this attribute exists, thenhidden
input elements which are inside thecollection-adder-form
will be cleared along with other input fields. By default,hidden
input elements are not cleared when the form is reset.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.consumers
: This allows you to connect thiscollection-adder-form
to other elements on your page. It should be used in conjunction with theprovider-template
attribute. Theconsumers
attribute takes a list of selectors with optional attributes to target in the formatelement-selector:attribute-name
. For example.my-input:value
will find all elements with amy-input
class and update theirvalue
attributes with the output of thecollection-adder-form
component on submit. You can specify multiple selectors separated by commas such as.my-input,my-div
; in this case, because attribute names are not specified, values will be injected into thevalue
attribute (for input elements) or into theinnerHTML
property (for other kinds of elements). The default attribute/property depends on the element type.success-consumers
: Same as theconsumers
attribute but the target elements are only updated if insertion was a success.error-consumers
: Same as theconsumers
attribute but the target elements are only updated if insertion was a failure.provider-template
: A template string within which the{{value}}
can be injected before passing to consumers. In the case of thecollection-adder-form
component, the value is an object with either aresource
property (on successful insert) orerror
(on failure). On success, theresource
object will be the object which was added to the collection. On failure, theerror
object will be a JavaScriptError
object with amessage
property.
Attributes of slotted input, select, textarea... elements
name
(required): This must correspond to a field name on the model specified via thecollection-type
attribute of thecollection-adder-form
.output-type
: An optional type to cast the value of the input element into when the form is submitted.
collection-deleter
A component which can be placed anywhere inside a collection-viewer
component to delete a specific item from a collection as a result of a user action (e.g. on click).
It supports either immediate deletion or deletion upon confirmation; in the latter case, the parent collection-viewer
must have a confirm-modal
component slotted into its modal
slot.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/collection-deleter.js" type="module" defer></script>
Example usage
<!-- Must be placed somewhere inside a collection-viewer component, typically inside the slotted item template. -->
<collection-deleter model-id="{{Product.id}}" onclick="deleteItem()">✕</collection-deleter>
OR (with confirmation step)
<!-- Must be placed somewhere inside a collection-viewer component, typically inside the slotted item template. -->
<collection-deleter model-id="{{Product.id}}" confirm-message="Are you sure you want to delete the {{Product.name}} product?" onclick="confirmDeleteItem()">✕</collection-deleter>
Attributes
model-id
(required): Specifies the ID of the resource to delete from the parent collection when this component is activated. This can be achieved by invoking either thedeleteItem()
orconfirmDeleteItem()
function from inside an event handler. The example above shows how to achieve deletion via theonclick
event. You can either invokedeleteItem()
to delete the resource immediately or you can invokeconfirmDeleteItem()
to require additional confirmation prior to deletion.onclick
(required): The logic to execute to delete the item. Should be eitherdeleteItem()
orconfirmDeleteItem()
.confirm-message
: The confirmation message to show the user when this component'sconfirmDeleteItem()
function is invoked.model-field
: If specified, this attribute can be used to delete a single field of a model instance, instead of the whole instance.
If confirmDeleteItem()
is used, then the parent collection-viewer
must have a confirm-modal
element slotted into it as shown here:
<collection-viewer
collection-type="Product"
collection-fields="name,qty"
collection-view="alphabeticalView"
collection-view-params=""
collection-page-size="50"
>
<template slot="item">
<div>
<div>{{Product.name}}</div>
<collection-deleter model-id="{{Product.id}}" confirm-message="Are you sure you want to delete the {{Product.name}} product?" onclick="confirmDeleteItem()">✕</collection-deleter>
</div>
</template>
<div slot="viewport" class="chat-viewport"></div>
<!-- The confirm-modal element must be specified here with slot="modal" to prompt the user for confirmation -->
<confirm-modal slot="modal" title="Delete confirmation" message="" confirm-button-label="Delete"></confirm-modal>
</collection-viewer>
collection-reducer
Similar to the collection-viewer
component but designed to render collections in combined format. For example, to combine values from multiple records into a single item.
A common use case is to extract and join values to pass to other child components via their attributes.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/collection-reducer.js" type="module" defer></script>
Example usage
<!--
Here, the collection-reducer fetches all available categories and joins their name fields
to use as options for a model-input select element.
This allows the user to choose among available category names to update the
current product's categoryName field.
You should assume that {{productId}} comes from a parent component (e.g. app-router).
-->
<collection-reducer
collection-type="Category"
collection-fields="name"
collection-view="alphabeticalView"
collection-page-size="100"
collection-view-params=""
>
<template slot="item">
<div class="form">
<label class="label-container">
<div>Product category</div>
<model-input
type="select"
options="{{joinFields(Category, 'name')}}"
model-type="Product"
default-value="accountId"
model-id="{{productId}}"
model-field="categoryName"
></model-input>
</label>
</div>
</template>
<div slot="viewport"></div>
</collection-reducer>
Unlike with collection-viewer
or model-viewer
, the template variable references not a single model instance but an array of model instances.
In the example above, the name of the first element can be accessed with {{Category[0].name}}
.
Attributes
collection-type
(required): Specifies the type of collection to use. This should match aModel
available in your Saasufy service.collection-fields
(required): A comma-separated list of fields from theModel
that you want to use. This lets you pick specific pieces of data from your collection to work with.collection-view
(required): Determines the view of the collection. This should match one of theViews
defined in your Saasufy service under that specificModel
.collection-view-params
(required): Parameters for the view, specified as comma-separated key-value pairs (e.g., key1=value1,key2=value2). These parameters can customize the behavior of the collection view. The keys must matchparamFields
specified in your Saasufy service under the relevantView
.collection-page-size
: Sets how many items from the collection are displayed at once. This is useful for pagination, allowing users to navigate through large sets of data in chunks.collection-page-offset
: Indicates the current page offset in the collection's data. It’s like telling the viewer which page of data you want to display initially.collection-get-count
: If this attribute is present, the component will get the record count of the target view. The count can be rendered into the template by prefixing the model name with a dollar sign and accessing thecount
property like this:{{$MyModelName.count}}
.type-alias
: Allows you to provide an alternative name for yourModel
to use when injecting values inside the template. This is useful for situations where you may have multiplecollection-viewer
elements and/ormodel-viewer
elements of the same type nested inside each other and want to avoidModel
name clashes in the nested template definitions. For example, if thetype-alias
in the snippet above was set toSubChat
, then{{Chat.message}}
would become{{SubChat.message}}
.hide-error-logs
: A flag which, when present, suppresses error logs from being printed to the console.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
model-input
Used for displaying and editing a single field of a model instance in realtime.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/model-input.js" type="module" defer></script>
Example usage
<model-input
type="text"
model-type="Product"
model-id="{{productId}}"
model-field="name"
placeholder="Product name"
></model-input>
Attributes
model-type
(required): Specifies the type of model to bind to. This should match aModel
available in your Saasufy service.model-id
(required): The id of the model instance/record to bind to.model-field
(required): The field of the model instance/record to bind to for reading and updating.debounce-delay
: The delay in milliseconds to wait before sending an update to the server. This is useful to batch multiple updates together (as is common when user is typing). Default is 300ms.disable-instant-flush
: If specified, changes will only be saved once they have settled (E.g. after the element has lost focus or when the enter key is pressed).list
: If specified, this sets the list attribute of the innerinput
element to provide input suggestions (only works with standard input elements).type
: The type of the input component; can betext
,number
,select
,textarea
,checkbox
orfile
.placeholder
: Can be used to set the placeholder text on the inner input element.consumers
: This allows you to connect thismodel-input
to other elements on your page. It takes a list of selectors with optional attributes to target in the formatelement-selector:attribute-name
. For example.my-input:value
will find all elements with amy-input
class and update theirvalue
attributes with the value of themodel-input
component in real-time. You can specify multiple selectors separated by commas such as.my-input,my-div
; in this case, because attribute names are not specified, values will be injected into thevalue
attribute (for input elements) or into theinnerHTML
property (for other kinds of elements). The default attribute/property depends on the element type. Note thatmodel-input
elements of thefile
type are treated as write-only unless theconsumers
attribute is present.provider-template
: A template string within which the{{value}}
can be injected before passing to consumers.show-error-message
: If this attribute is present, an error message will be displayed above the input if it fails to update the value.options
: A comma-separated list of options to provide - This only works if the input type isselect
.height
: Allows you to set the height of the innerinput
element programmatically.default-value
: A default value to show the user if the underlying model field's value is null or undefined. Note that setting a default value will not affect the underlying model's value.value
: Used to set the model's value.computable-value
: If this attribute is present, it will be possible to execute expressions using the{{expression}}
syntax inside thevalue
attribute.slice-to
: Optional attribute which can be set to a number to trim strings down to a maximum number of characters. This is useful when dealing with potentially very long field values. Extra care should be taken when using this attribute on amodel-input
element as it will cause values to be overwritten with shortened values if the user edits the input box. Note also that it may affect caching if the same field is being referenced in multiple parts of the application at the same time within the samesocket-provider
.hide-error-logs
: By default, this component will log errors to the console. If set, this attribute will suppress such errors from showing up on the console.autocapitalize
: Can beon
oroff
- It will set the auto-capitalize attribute on the inner input element. This is useful for mobile devices to enable or disable auto-capitalization of the first character which is typed into the input element.autocorrect
: Can beon
oroff
- It will set the auto-correct attribute on the inner input element. This is useful for mobile devices to enable or disable auto-correct.enable-rebound
: By default, for efficiency reasons, real-time updates performed viamodel-input
components are not sent back to the publishing client; it is usually unnecessary because state changes are shared locally between all components which are bound to the samesocket-provider
. You can add theenable-rebound
attribute to themodel-input
component to force real-time updates to rebound back to the publisher to support more advanced scenarios. Note that enabling rebound comes with additional performance overheads.accept
: This attribute should only be used if thetype
is set tofile
; it serves to constrain the types of files which can be selected by the user.input-id
: Can be used to set anid
attribute on the innerinput
element.input-props
: Can be used to set additional attributes on the innerinput
element. Must be in the formatattr1=value1,attr2=value2
.ignore-invalid-selection
: Can be used with amodel-input
component of typeselect
to prevent theerror
class from being added if the selected value is not among the available options.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
model-text
Used to displaying a field of a model instance in realtime.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/model-text.js" type="module" defer></script>
Example usage
<model-text
type="text"
model-type="Product"
model-id="{{productId}}"
model-field="name"
></model-text>
Attributes
model-type
(required): Specifies the type of model to bind to. This should match aModel
available in your Saasufy service.model-id
(required): The id of the model instance/record to bind to.model-field
(required): The field of the model instance/record to bind to for reading.slice-to
: Optional attribute which can be set to a number to trim strings down to a maximum number of characters when reading. This is useful when dealing with potentially very long field values. Note that it may affect caching if the same field is being referenced in multiple parts of the application at the same time within the samesocket-provider
.default-value
: A default value to show the user if the underlying model field's value is null or undefined.hide-error-logs
: By default, this component will log errors to the console. If set, this attribute will suppress such errors from showing up on the console.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
model-viewer
Used for rendering a single model resource using a template. This is the single-model alternative to the collection-viewer
which works with collections of models.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/model-viewer.js" type="module" defer></script>
Example usage
<model-viewer
model-type="Product"
model-id="{{modelId}}"
model-fields="name,desc,qty"
>
<template slot="item">
<div>
<div>Name: {{Product.name}}</div>
<div>Description: {{Product.desc}}</div>
<div>Quantity: {{Product.qty}}</div>
</div>
</template>
<div slot="viewport"></div>
</model-viewer>
Attributes
model-type
(required): Specifies the type of model to bind to. This should match aModel
available in your Saasufy service.model-id
(required): The id of the model instance/record to bind to.model-fields
(required): A comma-separated list of fields to bind to. Note that unlike withmodel-input
andmodel-text
, the attribute name is plural and can bind to multiple fields.type-alias
: Allows you to provide an alternative name for yourModel
to use when injecting values inside the template. This is useful for situations where you may have multiplemodel-viewer
elements and/ormodel-viewer
elements of the same type nested inside each other and want to avoidModel
name clashes in the nested template definitions. For example, if thetype-alias
in the snippet above was set toMyProduct
, then{{Product.name}}
would become{{MyProduct.name}}
.fields-slice-to
: Optional attribute which can be used to trim strings down to a maximum number of characters when reading. The format isfieldName1=number1,fieldName2=number2
. This is useful when dealing with potentially very long field values. Note that it may affect caching if the same field is being referenced in multiple parts of the application at the same time within the samesocket-provider
.hide-error-logs
: A flag which, when present, suppresses error logs from being printed to the console.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
input-provider
An input component which can pass data to other components (or HTML elements) via custom attributes.
A common use case for it is to pass user input to collection-viewer
or model-viewer
components to then fetch data from Saasufy.
This component can be configured to provide its data to multiple components (consumers) via custom attributes.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/input-provider.js" type="module" defer></script>
Example usage
<input-provider
type="text"
consumers=".my-input"
value="Hello world!"
placeholder="Message"
></input-provider>
Attributes
input-id
: Can be used to set anid
attribute on the innerinput
element.list
: If specified, this sets the list attribute of the innerinput
element to provide input suggestions (only works with standard input elements).type
: The type of the input component; can betext
,number
,select
,textarea
orcheckbox
.disable-instant-flush
: If specified, changes will only be saved once they have settled (E.g. after the element has lost focus or when the enter key is pressed).placeholder
: Can be used to set the placeholder text on the inner input element.consumers
: This allows you to connect thisinput-provider
to other elements on your page. It takes a list of selectors with optional attributes to target in the formatelement-selector:attribute-name
. For example.my-input:value
will find all elements with amy-input
class and update theirvalue
attributes with the value of theinput-provider
component in real-time. You can specify multiple selectors separated by commas such as.my-input,my-div
; in this case, because attribute names are not specified, values will be injected into thevalue
attribute (for input elements) or into theinnerHTML
property (for other kinds of elements). The default attribute/property depends on the element type.provider-template
: A template string within which the{{value}}
can be injected before passing to consumers.debounce-delay
: The delay in milliseconds to wait before triggering a change event. This is useful to batch multiple updates together (as is common when user is typing). Default is 800ms.options
: A comma-separated list of options to provide - This only works if the input type isselect
.height
: Allows you to set the height of the innerinput
element programmatically.value
: Used to set the input's value.computable-value
: If this attribute is present, it will be possible to execute expressions using the{{expression}}
syntax inside thevalue
attribute.autocapitalize
: Can beon
oroff
- It will set the auto-capitalize attribute on the inner input element. This is useful for mobile devices to enable or disable auto-capitalization of the first character which is typed into the input element.autocorrect
: Can beon
oroff
- It will set the auto-correct attribute on the inner input element. This is useful for mobile devices to enable or disable auto-correct.input-props
: Can be used to set additional attributes on the innerinput
element. Must be in the formatattr1=value1,attr2=value2
.skip-init-change
: This attribute can be used to prevent aninput-provider
from triggering a change when initialized with a default value. By default, theinput-provider
will trigger a change when initialized with a default value.force-init-change
: This attribute can be used to force aninput-provider
to always trigger a change when initialized, even if the value is empty.
input-combiner
A component which can be used to combine data from multiple input-provider
components and pass the combined data to other components (or HTML elements) via custom attributes.
A common use case for it is to pass user input to collection-viewer
or model-viewer
components to then fetch data from Saasufy.
This component can be configured to provide its data to multiple components (consumers) via custom attributes.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/input-combiner.js" type="module" defer></script>
Example usage
The following example shows how to bind multiple input-provider
components to an input-combiner
.
In this example, the input-combiner
component forwards the combined, formatted values to the collection-view-params
attribute of a company-viewer
component.
Note that the value
inside the provider-template
attribute of the input-combiner
is an object with keys that represent the name
attribute of the different source input-provider
components.
The combineFilters
function produces a combined query string (joined with %AND%
) by iterating over the value
object which holds different parts of the query as provided by different input-provider
components.
<input-provider
class="desc-input"
name="desc"
type="text"
consumers=".search-combiner"
provider-template="description contains (?i){{value}}"
value=""
placeholder="Description filter"
></input-provider>
<input-provider
class="city-input"
name="city"
type="text"
consumers=".search-combiner"
provider-template="city contains (?i){{value}}"
value=""
placeholder="City filter"
></input-provider>
<input-combiner
class="search-combiner"
consumers=".company-viewer:collection-view-params"
provider-template="query='{{combineFilters(value)}}'"
></input-combiner>
Attributes
consumers
: This allows you to connect thisinput-combiner
to other elements on your page. It takes a list of selectors with optional attributes to target in the formatelement-selector:attribute-name
. For example.my-input:value
will find all elements with amy-input
class and update theirvalue
attributes with the value of theinput-provider
component in real-time. You can specify multiple selectors separated by commas such as.my-input,my-div
; in this case, because attribute names are not specified, values will be injected into thevalue
attribute (for input elements) or into theinnerHTML
property (for other kinds of elements). The default attribute/property depends on the element type.provider-template
: A template string within which the{{value}}
can be injected before passing to consumers. In the case of theinput-combiner
, the value is an object wherein each key represents the unique label associated with differentinput-provider
components.debounce-delay
: The delay in milliseconds to wait before triggering a change event. This is useful to batch multiple updates together. Default is 500ms.
input-transformer
A component which can be used to transform data from an input-provider
component and pass the transformed data to other components (or HTML elements) via custom attributes.
This component can be configured to provide its data to multiple components (consumers) via custom attributes.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/input-transformer.js" type="module" defer></script>
Example usage
The following example shows how to bind an input-provider
component to an input-transformer
.
<input-provider
class="dollar-input"
name="count"
type="text"
consumers=".cents-transformer"
value=""
placeholder="Dollars"
></input-provider>
<input-transformer
class="cents-transformer"
consumers=".cents-container"
provider-template="{{Number(value) * 100}}"
></input-transformer>
<div class="cents-container"></div>
Attributes
consumers
: This allows you to connect thisinput-transformer
to other elements on your page. It takes a list of selectors with optional attributes to target in the formatelement-selector:attribute-name
. For example.my-input:value
will find all elements with amy-input
class and update theirvalue
attributes with the value of theinput-provider
component in real-time. You can specify multiple selectors separated by commas such as.my-input,my-div
; in this case, because attribute names are not specified, values will be injected into thevalue
attribute (for input elements) or into theinnerHTML
property (for other kinds of elements). The default attribute/property depends on the element type.provider-template
: A template string within which the{{value}}
can be injected before passing to consumers.output-type
: The default output type isstring
. This property can be used to convert the output to eitherboolean
ornumber
.debounce-delay
: The delay in milliseconds to wait before triggering a change event. This is useful to batch multiple updates together. Default is 0ms.
log-in-form
A form component which allows end-users to authenticate themselves into your app using the Saasufy blockchain or any Capitalisk-based blockchain.
On success, the socket of the form's socket-provider
will be set to the authenticated state; this will then cause appropriate Saasufy components which share this socket-provider
to reload themselves.
Once a user is authenticated, they will be able to access restricted data (as specified on the Saasufy Model -> Access
page).
It's also possible to specify a success-location-hash
attribute to trigger a client-side redirect upon successful authentication.
The change in the location hash can then be detected by an app-router
to switch to a different page upon successful login.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/log-in-form.js" type="module" defer></script>
Example usage
<log-in-form
hostname="capitalisk.com"
port="443"
network-symbol="clsk"
chain-module-name="capitalisk_chain"
secure="true"
></log-in-form>
Attributes
hostname
(required): The hostname of the blockchain node to match authentication details against.port
(required): The port of the blockchain node to match authentication details against. Should be 80 for HTTP/WS or 443 for HTTPS/WSS.network-symbol
(required): The symbol of the target blockchain.chain-module-name
(required): The module name used by the target blockchain.secure
(required): Should betrue
orfalse
depending on whether or not the node is exposed over HTTP/WS or HTTPS/WSS.auth-timeout
: The maximum number of milliseconds to wait for authentication to complete. Defaults to 10000 (10 seconds).success-location-hash
: If authentication is successful, the browser'slocation.hash
will be set to this value. It can be used to redirect the user to their dashboard, for example.greedy-refresh
: If this attribute exists, the component will refresh itself whenever an attribute is set, even if that attribute's value did not change.
log-out
A component which can be placed inside a socket-provider
to deauthenticate the socket (e.g. on click).
Import
<script src="https://saasufy.com/node_modules/saasufy-components/log-out.js" type="module" defer></script>
Example usage
<log-out onclick="logOut()"><a href="javascript:void(0)">Log out</a></log-out>
oauth-link
A link to initiate an OAuth flow to authenticate a user as part of log in. Can support a range of different OAuth providers.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/oauth-link.js" type="module" defer></script>
Example usage
<oauth-link class="log-in-oauth-section" provider="github" client-id="dabb51f8af31a0bc53bf">
<template slot="item">
<a href="https://github.com/login/oauth/authorize?client_id={{oauth.clientId}}&state={{oauth.state}}">
Log in with GitHub
</a>
</template>
<div slot="viewport"></div>
</oauth-link>
Attributes
provider
(required): The name of the provider. It must match the provider name specified on theAuthentication
page of your Saasufy control panel and also the value provided to theoauth-handler
component at the end of the OAuth flow.client-id
(required): This is the client ID from the third-party OAuth provider.state-size
: This allows you to control the size (in bytes) of the random state string which is passed to the OAuth provider as part of the OAuth flow. Defaults to 20.state-storage-key
: The state string is stored in the browser'ssessionStorage
under this key. Defaults tooauth.state
. It must match the value provided to theoauth-handler
component at the end of the OAuth flow.use-local-storage
: By default, the state is stored inside sessionStorage. If this property is set, then the state will be stored inside localStorage instead. This is useful for sharing the state across different tabs. If set, this attribute should also be set on the relatedoauth-handler
component.
oauth-handler
This component handles the final stage of OAuth and then redirects the user to the relevant page/URL if successful.
When using an OAuth provider, the callback URL which you register with the provider must lead the user back to a page which contains this oauth-handler
component.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/oauth-handler.js" type="module" defer></script>
Example usage
<oauth-handler provider="github" success-location-hash="/chat"></oauth-handler>
Attributes
provider
(required): The name of the provider. It must match the provider name specified on theAuthentication
page of your Saasufy control panel and also the value provided to theoauth-link
component at the start of the OAuth flow.success-location-hash
: If authentication is successful, the browser'slocation.hash
will be set to this value. It can be used to redirect the user to their dashboard, for example.success-url
: If authentication is successful, the browser'slocation.href
will be set to this value. It can be used to redirect the user to their dashboard, for example.extra-data
: This attribute can be used to pass additional data to the OAuthgetAccessTokenURL
endpoint. For Google OAuth, for example, an additionalredirect_uri
field is required, so it should be set usingextra-data="redirect_uri=http://localhost.com:8000/"
(substitute the URI with your own).navigate-event-path
: If authentication is successful and a path is set via this attribute, the component will emit anavigate
event which will bubble up the component hierarchy and can be used by a parent component to perform the success redirection. This approach can be used as an alternative tosuccess-location-hash
orsuccess-url
for doing the final redirect.state-storage-key
: The state string is stored in the browser'ssessionStorage
under this key. Defaults tooauth.state
. It must match the value provided to theoauth-link
component at the start of the OAuth flow.code-param-name
: The name of the query parameter which holds thecode
as provided by the OAuth provider within the OAuth callback URL. Defaults tocode
.state-param-name
: The name of the query parameter which holds thestate
as provided by the OAuth provider within the OAuth callback URL. Defaults tostate
.auth-timeout
: The number of milliseconds to wait for authentication to complete before timing out. Defaults to 10000 (10 seconds).use-local-storage
: By default, the state is retrieved from sessionStorage. If this property is set, then the state will be retrieved from localStorage instead. This is useful for sharing the state across different tabs. If set, this attribute should also be set on the relatedoauth-link
component.
render-group
A component which can be used to guarantee that certain children components are always rendered at the same time (once they are loaded) to provide a smooth user experience.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/render-group.js" type="module" defer></script>
Example usage
<render-group wait-for="1,2,3">
<model-input
type="text"
load-id="1"
model-type="Product"
model-id="{{productId}}"
model-field="name"
></model-input>
<model-input
type="text"
load-id="2"
model-type="Product"
model-id="{{productId}}"
model-field="desc"
></model-input>
<model-input
type="number"
load-id="3"
model-type="Product"
model-id="{{productId}}"
model-field="qty"
></model-input>
</render-group>
Attributes
wait-for
(required): A list of components to wait for before rendering based on theirload-id
attributes. Therender-group
will only render its content once all the components specified via this attribute have finished loading their data.
if-group
A component which exposes a show-content
property which can be set to true or false to show or hide its content.
It's intended to be placed inside a model-viewer
, collection-viewer
or collection-reducer
component such that the true/false value of the show-content
attribute can be computed using a template {{expression}}
placeholder. This component requires a template and a viewport to be slotted in. The content of the template will not be processed unless the show-content
condition is met.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/if-group.js" type="module" defer></script>
Example usage
<if-group show-content="{{!!Product.isVisible}}">
<template slot="content">
<div>Name: {{Product.name}}</div>
<div>Description: {{Product.desc}}</div>
<div>Quantity: {{Product.qty}}</div>
</template>
<div slot="viewport"></div>
</if-group>
switch-group
A component which exposes a show-cases
property which can be set to key-value pairs in the format key1=true,key2=false
. It can be used to conditionally display multiple slotted elements based on multiple conditions. It helps to keep HTML clean when the conditions are complex.
This element is intended to be placed inside a model-viewer
, collection-viewer
or collection-reducer
component such that the true/false values of the show-cases
attribute can be computed using template {{expression}}
placeholders. This component requires one or more templates and a viewport to be slotted in. The content of the templates will not be processed unless the show-cases
condition is met. All templates must have a slot="content"
attribute and a name attribute in the format name="key1"
where the value key1
corresponds to the key specified inside the show-cases
attribute of the switch-group
.
Import
<script src="https://saasufy.com/node_modules/saasufy-components/switch-group.js" type="module" defer></script>
Example usage
<switch-group show-cases="image={{!!Section.imageURL}},text={{!!Section.text}}">
<template slot="content" name="image">
<img src="{{Section.imageURL}}" alt="{{Section.imageDesc}}" />
</template>
<template slot="content" name="text">
<div>{{Section.text}}</div>
</te