I'm new to ignition module development and I would like to know if it is possible to build a module that create and register custom perspective components to the designer. Would appreciate pointers into the right directions in any ways as I've struggling to find the useful resource or examples.
I would like to have a custom perspective components that display data which is obtained from querying the database. From my understanding we can bind a property to database query via query binding with named query and ignition handles that nicely. However, named query seems to be project scoped, which means I'd have to create the query for each project. Is there a way to have a query that is available across all project that can be used to bind to a component's property?
Ideally, I would like the component to have its data property to default to the query binding and select a default query, and the query will have params to it which may alter data returned (data format still same). Any idea if this will be possible?
I'm not sure if doing this via property data binding is a good idea, or if they should be done within the perspective component. Any help would be appreciated. Thanks in advanced
Use project inheritance. Define your named query in an inheritable project and have your various UI projects inherit from that. In my recommended hierarchy, that would be in the perspective_common project:
Project inheritance is definitely the simplest option here, not requiring a custom module at all.
If you do decide to go with a custom module, I would skip the custom component that's pre-registered with a default binding, and just register a custom binding type in your module.
I want to build a custom perspective component and make it available under "Perspective Components" in the Designer for users to add into their views. And the only way I see this from happening is through building a module. Correct me if I am wrong here.
I don't quite get what you mean by register a custom binding type in your module, could you explain further on this?
Essentially I'll have data in the database (connected from gateway) that I want the component to query from and display the data. And I want to abstract away the query (or make it reusable across projects) so that when the user wants to use the component, they won't have to worry about the query details, they just need to pass in a few parameters to the query and that's it.
Ignition's query bindings are extraordinarily flexible. If you really want users to not worry about the behavior of the query inside your component, do not put the query inside your component.
You are re-inventing the wheel. You are unlikely to do this as well as IA already did, with query bindings. Really. Don't have your component run its own queries.
IA has some components that run their own queries. They are frustrating to use and utterly inflexible. Don't follow that example.
Is your suggestion to just have the custom component that have properties in the desired format, and when using the component, user can use query binding to get the data? Although this seems to be nice, I don't see how this abstracts away the query from the user. Perhaps I can have a named query that gets created by the module in a inheritable project and ensure all project inherits it? Then user can just select the custom component and select the named query for query binding? It just worries me that the module cannot ensure the named query exists.
I've been looking at the ignition-sdk-examples for perspective components. It looks like with the tag counter it is fetching data from a endpoint hosted on the gateway. This seems like another approach to get data from the database (via the endpoint hosted in gateway which I'm guessing can query the database) and display the data in the component. I will still need property as input to the component to select certain fields, for e.g., a machine id, and i can pass that to the endpoint to filter data being returned. Will this be a recommended approach?
Perspective fully supports registration of additional binding types by modules. That is, the 'Tag', 'HTTP', 'Expression', etc binding types - are just registered artifacts. So you can register your own binding type, with its own customization UI and whatever parameters make sense for it, with Perspective, and from your end user's perspective () it just looks like a native part of the product.
Exposing simple properties and running your own code in the backend is also absolutely an option - but Phil and I share the view that this limits your component's flexibility to detrimental effect.
In other words:
If you define a custom component that also does its own data fetching, you are tightly coupling your data model and your presentation model.
Compare/contrast Perspective's Table component and the Alarm Status Table component. The former is only [1] concerned with displaying some kind of data, and has huge support for customization and flexibility. The latter is only concerned with one kind of data, and thus can only do one thing, and also doesn't have support for the same amount of customization because it's always one piece; it's not assembled out of component pieces.
This is, ultimately, more of a philosophical argument than a strict technical one. You absolutely don't have to follow what Phil and I are saying here - as I just said, even Inductive doesn't follow this advice consistently. But in general, especially given what you've described so far, I would not want to go the custom component route. Only if you have a new fundamental building block that can't be composed out of our existing "primitive"s would I reach that far.
What I'm trying to build is in fact a component that is only concern with one kind of data.
As for background context, I'll have the gateway connected to a database (postgres) with tables and data that I'm interested in. In the designer, I want a custom component that handles the data querying logic behind the scene. It does need some simple property as input that will be passed to the query as params to filter the data. I'm aware that this isn't a recommended approach in terms of flexibility of the component but it make sense for what I'm trying to build here.
My questions now turns into if it is possible to build a custom component like this, that queries the database for the data. And if so, how does it look like
architecturally. An approach I can think of is to host endpoints in the gateway that does the database queries logic and return the data and have the component to call the endpoint, and probably needing to handle polling to keep the data up to date. Or will it be better to use RPC instead of endpoint. I'm just trying to explore the available options here and coming up with potential workable ideas. Do you have any better ideas?
Anyways idk if its the best mothode but i ones made a componet with an extension with default code in it, so it can be overwritten. Maybe thats a better option.