|
1 | | -# Custom libraries |
2 | | -Custom libraries are a way to store own created views with different presentation types. |
| 1 | +# External libraries |
3 | 2 |
|
4 | | -To create a custom components library, two projects must be created: |
5 | | -- **Connector project** - which will contain PLC compiled classes from Ix Builder. |
6 | | -- **Razor components project** - Razor class library, which will contain the implementation of corresponding views with dependency on Connector project. |
| 3 | +External libraries can store user defined views in different presentation types, which then can be dynamically rendered. |
7 | 4 |
|
8 | | -It is important to note that the generated classes in the Connector project and created Razor views must be in **same namespace** to correctly locate views. |
| 5 | +This file describes how to create external library and connect it to the PLC project. Look at **integration-blazor** project example. |
9 | 6 |
|
10 | | -See the example below: |
| 7 | +Make sure Blazor server project and PLC projects are created. |
11 | 8 |
|
12 | | -We have three projects: |
13 | | -- *ComponentsExamples* - custom components library |
14 | | -- *IxBlazor.App* - Blazor Server application |
15 | | -- *PlcConnector* - class library containing generated files from IX Builder |
| 9 | +## Razor class library setup |
16 | 10 |
|
17 | | -Files in the *ComponentsExample* and the *PlcConnector* are in the same namespace. *IxBlazor.App* has a reference to the *ComponentsExample* project. |
| 11 | +### 1. Create library |
18 | 12 |
|
19 | | - |
| 13 | +Create Razor class library in your solution. |
20 | 14 |
|
21 | | -*ComponentsExamples* library must contain `RenderableBlazorAssemblyAttribute()`. Thanks to this attribute RenderableContentControl is able to load its assembly and find all created custom view. |
22 | 15 |
|
23 | | -This attribute can be added to `AssemblyInfo.cs` class located in `Properties` folder. If there is no `Properties` folder, just create it with `AssemblyInfo.cs` class and paste there following code: |
| 16 | +### 2. Add references |
24 | 17 |
|
25 | | -```C# |
| 18 | + |
| 19 | +- Install `Ix.Presentation.Blazor.Controls` nuget package or if you are using raw projects, add reference to `Ix.Presentation.Blazor.Controls` project. |
| 20 | + |
| 21 | +- Add reference from Razor Class library to PLC project. |
| 22 | + |
| 23 | +- In Blazor Server app, add reference to newly created Razor class library. |
| 24 | + |
| 25 | +Dependency graph should look like this: |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +### 3. Add namespace |
| 31 | + |
| 32 | +Add namespace of renderer to `_Imports.razor` in razor class library. |
| 33 | +``` |
| 34 | +@using Ix.Presentation.Blazor.Controls.RenderableContent |
| 35 | +``` |
| 36 | +### 4. Add renderable attribute |
| 37 | + |
| 38 | +Add `RenderableBlazorAssemblyAttribute` to Razor class library. |
| 39 | + |
| 40 | +1. Create folder named `Properties` |
| 41 | +2. Inside folder create `AssemblyInfo.cs` class |
| 42 | +3. Copy following code into `AssemblyInfo.cs` class: |
| 43 | + |
| 44 | +``` |
| 45 | +using System.Reflection; |
26 | 46 | using Ix.Presentation.Blazor.Attributes; |
27 | 47 |
|
28 | 48 | [assembly: RenderableBlazorAssemblyAttribute()] |
| 49 | +
|
29 | 50 | ``` |
30 | 51 |
|
| 52 | +Thanks to this attribute, renderer will load assembly of created class library and it is able to look for custom defined views. |
31 | 53 |
|
| 54 | +--- |
| 55 | +## Create custom view |
32 | 56 |
|
33 | | -There are two ways for implementation of custom component: |
34 | | -- Custom component with **code-behind** |
35 | | -- Custom component with **ViewModel** support |
| 57 | +### 1. Create PLC structure and its instance |
36 | 58 |
|
37 | | -## Component with code-behind |
38 | | -This is simple approach, where Blazor view inherits from `RenderableComplexComponentBase<T>` base class, where `T` is your custom component PLC type. However logic of your component must be specified in code-behind of view class. Important is, that both view and code-behind must be in same namespace as your `PlcConnector`. |
| 59 | +``` |
| 60 | +CLASS ixcomponent |
| 61 | + VAR PUBLIC |
| 62 | + {#ix-set:AttributeName = "My integer"} |
| 63 | + my_int : INT; |
| 64 | + {#ix-set:AttributeName = "My string"} |
| 65 | + my_string : STRING; |
| 66 | + {#ix-set:AttributeName = "My bool"} |
| 67 | + my_bool : BOOL; |
| 68 | + END_VAR |
| 69 | +END_CLASS |
| 70 | +``` |
39 | 71 |
|
40 | | -Look at the example below: |
| 72 | +``` |
| 73 | +ixcomponent_instance: ixcomponent; |
| 74 | +``` |
41 | 75 |
|
42 | | -Blazor view `IxComponentServiceView.razor`: |
| 76 | +Build plc project with `apax build` and compile it with `apax ixc` command. |
| 77 | + |
| 78 | +### 2. Create IxComponentView in Razor class library |
| 79 | + |
| 80 | +- Create folder with name `IxComponentView`. |
| 81 | +- Create `IxComponentView.razor` class inside folder. |
| 82 | +- Define your view. |
43 | 83 |
|
44 | 84 | ```C# |
45 | | -@namespace Plc |
46 | | -@inherits RenderableComplexComponentBase<IxComponent> |
| 85 | +@namespace Ix.Presentation.Blazor.Controls.Templates |
| 86 | +@inherits RenderableComplexComponentBase<ixcomponent> |
47 | 87 |
|
48 | | -<h3>IxComponentServiceView</h3> |
| 88 | +<h1>IxComponentView</h1> |
49 | 89 |
|
50 | | -<p>IxBool serviceView: @Component.ix_bool.Cyclic</p> |
51 | | -<p>IxInt serviceView: @Component.ix_int.Cyclic</p> |
52 | | -<p>IxString serviceView: @Component.ix_string.Cyclic</p> |
| 90 | +<div class="card"> |
| 91 | + <p>IxBool: @Component.my_bool.Cyclic</p> |
| 92 | + <p>IxInt: @Component.my_int.Cyclic</p> |
| 93 | + <p>IxString: @Component.my_string.Cyclic</p> |
| 94 | +</div> |
53 | 95 |
|
54 | | -``` |
55 | | -`IxComponentServiceView.razor` view inherits from `RenderableComplexComponentBase<IxComponent>`. Thanks to this, framework will inject instance of *IxComponent* type into *Component* variable. After that, you can access values of *Component* variable and define logic of your custom component in code-behind. Code-behind must be partial class with the same name as view. |
56 | 96 |
|
57 | | -Code-behind `IxComponentServiceView.cs`: |
58 | | -```C# |
59 | | -namespace Plc |
60 | | -{ |
61 | | - public partial class IxComponentServiceView |
| 97 | +@code{ |
| 98 | + protected override void OnInitialized() |
62 | 99 | { |
63 | | - protected override void OnInitialized() |
64 | | - { |
65 | | - UpdateValuesOnChange(Component); |
66 | | - } |
| 100 | + UpdateValuesOnChange(Component); |
67 | 101 | } |
68 | 102 | } |
69 | 103 |
|
70 | 104 | ``` |
71 | 105 |
|
72 | | -If you want your UI to be updated everytime, when PLC values change, you must call `UpdateValuesOnChange(Component)` method in `OnInitialized()` method in code-behind. |
| 106 | +Note: If your plc variable is declared in global namespace, `Ix.Presentation.Blazor.Controls.Templates` namespace must be used to correctly locate view. |
| 107 | + |
| 108 | +If you plc variable is declared in your own namespace, make sure **namespace of custom view is the same as the namespace in plc file**. |
| 109 | + |
| 110 | +At the end, structure of external library should look like this: |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | +### Render custom component in your application |
| 115 | + |
| 116 | +``` |
| 117 | +<RenderableContentControl Context="@Entry.Plc.test_example.ixcomponent_instance"/> |
| 118 | +``` |
| 119 | + |
| 120 | +If everything was done correctly, custom view defined in external library should be rendered. |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | +--- |
| 125 | + |
73 | 126 |
|
74 | | -## Component with ViewModel |
75 | 127 |
|
76 | | -With this approach it is possible to create component using MVVM design pattern. |
| 128 | +## ViewModel approach |
77 | 129 |
|
78 | | -First, ViewModel must be created, which will inherits from abstract class `RenderableViewModelBase`: |
| 130 | +Renderer also supports injecting view-model classes into views. This enables to create custom components with MVVM pattern, where component logic can be placed into viewmodel class. Therefore, the code will be less coupled and more testable. |
79 | 131 |
|
80 | | -ViewModel `IxComponentBaseViewModel.cs` |
| 132 | + |
| 133 | +### 1. Create IxComponentServiceViewModel folder |
| 134 | +Create `IxComponentServiceView.razor` file and `IxComponentViewModel.cs` file inside folder. |
| 135 | + |
| 136 | + |
| 137 | +### 2. Define your viewmodel |
| 138 | +Make sure, that viewmodel inherits from `RenderableViewModelBase`. |
| 139 | +Copy following code into `IxComponentViewModel.cs` viewmodel class. |
81 | 140 | ```C# |
82 | | -namespace Plc |
| 141 | +using Ix.Presentation; |
| 142 | + |
| 143 | +namespace ix_integration_library.IxComponentServiceViewModel |
83 | 144 | { |
84 | | - public class IxComponentBaseViewModel : RenderableViewModelBase |
| 145 | + public class IxComponentServiceViewModel : RenderableViewModelBase |
85 | 146 | { |
86 | | - public IxComponentBaseViewModel() |
| 147 | + public IxComponentServiceViewModel() |
87 | 148 | { |
88 | 149 | } |
89 | | - public IxComponent Component { get; set; } |
90 | | - public override object Model { get => this.Component; set { this.Component = value as IxComponent; } } |
| 150 | + public ixcomponent Component { get; set; } |
| 151 | + public override object Model { get => this.Component; set { this.Component = value as ixcomponent; } } |
91 | 152 | } |
92 | 153 | } |
93 | 154 | ``` |
94 | | -After that, Blazor view `IxComponentBaseView.razor` can be created: |
| 155 | +Note: Replace namespace with namespace of your plc library. |
| 156 | + |
| 157 | +Copy following code into `IxComponentServiceView.razor` file. Make sure, that `RenderableViewModelComponentBase` class is inherited with generic type parameter of your viewmodel. |
95 | 158 |
|
96 | 159 | ```C# |
97 | | -@namespace Plc |
98 | | -@inherits RenderableViewModelComponentBase<IxComponentBaseViewModel> |
| 160 | +@namespace Ix.Presentation.Blazor.Controls.Templates |
| 161 | +@using ix_integration_library.IxComponentServiceViewModel |
| 162 | +@inherits RenderableViewModelComponentBase<IxComponentViewModel> |
99 | 163 |
|
100 | | -<h3>IxComponentBaseView</h3> |
| 164 | +<h1>IxComponentView with ViewModel</h1> |
101 | 165 |
|
102 | | -<p>IxBool baseView: @ViewModel.Component.ix_bool.Cyclic</p> |
103 | | -<p>IxInt baseView: @ViewModel.Component.ix_int.Cyclic</p> |
104 | | -<p>IxString baseView: @ViewModel.Component.ix_string.Cyclic</p> |
| 166 | +<div class="card"> |
| 167 | + <p>IxBool: @ViewModel.Component.my_bool.Cyclic</p> |
| 168 | + <p>IxInt: @ViewModel.Component.my_int.Cyclic</p> |
| 169 | + <p>IxString: @ViewModel.Component.my_string.Cyclic</p> |
| 170 | +</div> |
105 | 171 |
|
106 | | -@code |
107 | | -{ |
| 172 | + |
| 173 | +@code { |
108 | 174 | protected override void OnInitialized() |
109 | 175 | { |
110 | 176 | UpdateValuesOnChange(ViewModel.Component); |
111 | 177 | } |
112 | 178 | } |
113 | | - |
114 | 179 | ``` |
115 | | -The view must inherits from `RenderableViewModelComponentBase<T>` base class, where `T` is type of your ViewModel. Thanks to this, ViewModel instance is created and initialized with PLC type instance acquired within `RenderableContentControl`. After that, ViewModel can be accessed within Blazor view. |
116 | | - |
117 | | -If you want your UI update everytime, when PLC values change, you can add `UpdatesValuesOnChange(ViewModel.Component)` directly to code section in view, or you can create partial class same as in previous example. |
| 180 | +Note: viewmodel properties and variables can be accessed with inherited `ViewModel` variable. |
118 | 181 |
|
119 | | -When you call RenderableContentControl component like this: |
| 182 | +### 3. Render created component |
120 | 183 |
|
121 | | -``` |
122 | | -<RenderableContentControl Presentation="Base" |
123 | | - Context="@Entry.Plc.MAIN.instanceOfIxComponent"> |
124 | | -
|
125 | | -</RenderableContentControl> |
| 184 | +```C# |
| 185 | +<RenderableContentControl |
| 186 | + Presentation="Service" |
| 187 | + Context="@Entry.Plc.test_example.ixcomponent_instance" /> |
126 | 188 | ``` |
127 | 189 |
|
128 | | -You will get generated UI, which you specified in your custom view: |
| 190 | + |
129 | 191 |
|
130 | | - |
|
0 commit comments