This bundle is a set of tools allowing you to do beautiful frontends. Using the X-Framework.
You can easily create it by running
microservice, and select
We begin by defining our kernel, and our initial bundle
Now create a sample
UIAppBundle, and we ask it to load the routes.
And now we can finally render.
We add routes through the
XRouter. Routes are added programatically. Behind the scenes we use
Our strong recommendation is to never rely on strings for routes, this is why we'll add them in a route map and use it like this:
And now simply add them in your bundle like this:
Using the link and generating it:
The routes also support a
roles:  option:
An alternative would be to
useGuardian() and check for the role.
If the user doesn't have the role we render the
NotAuthorized component. Which can be overridden.
We have succcesfully blended D.I. with React. The concept is easy, you control your container inside the
init() phase of a bundle, you use it inside React. The right container is properly passed because everything is wrapped in
@apollo/client so in theory, all you have to do is just use it. You can follow the official guideline here, they will work outside the box without changing anything.
Collections are an interface to your remote database via
GraphQL as long as the remote queries and mutations respect a specific interface. That interface you get it in a snap when you create a
GraphQL CRUD from the cli command
Below, we'll have a simple example how to use the posts collection to find data.
Queries support both MongoDB filters and options:
We also support relational data, if relations are defined with
Nova in the backend:
We also support filtering the subset of relations:
Relational sorting means that you're sorting your current set, by a relation's field. For example you're listing all employees, and you want them sorted by company's name:
You can also find a single document with filters or by _id:
Counting documents is also easy:
This will transform the fetched result however you prefer, you can either instantiate a class with it using something like
class-transformers package, or just modify certain fields.
What we normally recommend is do this for
_id which are
ObjectId and to transform numbers to
Date for fields which are dates. Note it will only perform transformation if the response is not
To be able to perform deep transformation when fetching elements with relations, we need to define the links:
We have made the decision to not allow multi document updates or insertions due to security concerns. This is why we can only insert a single document, update document by _id, and remove it also by _id:
If you want to add additional collection specific logic, it would be advisable to put it in the class itself. This would allow you to re-use the code as you need it.
Integration with React is seamless and painless:
If you are expecting a single post, we also have an easy find by _id solution:
If you want to use the smart live data, just swap
useLiveData() and it will magically work, your data will be listening to changes.
You can also hook into the events, via the 4th argument, options:
When using live data and relations, it is by design to not have reactivity at nested levels. For example if someone updates the comments' text it won't trigger a reactive change. Instead you will have to create separate component that subscribes to that comment via
Smart is a very small library that does state management by using
useState() from React and
useContext() allowing you to easily split logic out of your components.
The difference here is that
Smart from this package, allows you to work with the D.I. container:
We have created a
Smart that allows you to easily work with lists:
Now we can use it in our components:
Now you can access
api.state from within
Component or via
api = useSmart(PostsList) in deeply nested children:
So you have acces to nice things now you will most likely play with:
The guardian is a smart that communicates with the server, providing authentication methods for
forgotPassword, resetPassword, verify email.
Explore the examples in this boilerplate
It also handles fetching the user data using the
me standard query, but this behavior can be later changed.
Let's use guardian in our components
The user type is the default one from
There are several reasons you would want to extend the guardian, most popular being
- Change registration input
- Fetch different set of data of the logged in user
We specify this class when we initialise
register calls the
registration mutation with the GraphQL input:
RegistrationInput. It's enough to change the input on the server-side by overriding
registration mutation in
However if you want to extend the interface of
Guardian, meaning you add other methods or add other variables to the existing methods, then besides overriding the
guardianClass you need to create your own hook, to benefit of autocompletion.
You can use the classic
EventManager to emit events, but if you want to have a component listen to events during its lifespan (until it gets unmounted), you can use the hook:
You have the ability to craft and override UI components:
Overriding them is done in the
init() phase of your bundle
Creating new components is done in two steps, first we extend the interface, second we update the components as shown in the overriding phase: