Skip to content

Commit 10d16ec

Browse files
authored
Merge pull request #7670 from umbraco/forms/ui-builder-prevaluesource
Forms: Add UI Builder repository PreValueSource example
2 parents 781e986 + 409c2b9 commit 10d16ec

File tree

8 files changed

+458
-0
lines changed

8 files changed

+458
-0
lines changed

16/umbraco-forms/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
* [Adding A Field Type To Umbraco Forms](developer/extending/adding-a-fieldtype.md)
5151
* [Excluding a built-in field](developer/extending/excluding-a-built-in-field.md)
5252
* [Adding A Prevalue Source Type To Umbraco Forms](developer/extending/adding-a-prevaluesourcetype.md)
53+
* [Adding a UI Builder repository as a prevalue source](developer/extending/uibuilder-repository-prevalue.md)
5354
* [Adding A Workflow Type To Umbraco Forms](developer/extending/adding-a-workflowtype.md)
5455
* [Adding An Export Type To Umbraco Forms](developer/extending/adding-a-exporttype.md)
5556
* [Adding a Magic String Format Function](developer/extending/adding-a-magic-string-format-function.md)
60.6 KB
Loading
51.8 KB
Loading
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# Adding a UI Builder repository as a prevalue source
2+
3+
When using [Umbraco UI Builder](https://docs.umbraco.com/umbraco-ui-builder/) alongside Umbraco Forms, you can use a configured UI Builder repository as a prevalue source.
4+
5+
To do this, you will need to create a custom `FieldPreValueSourceType` source that uses UI Builder's `SectionConfiguration` property editor. Once configured, you can select a repository and fetch the prevalues from there.
6+
7+
## Example
8+
9+
The following class shows how to create a `UIBuilderRepository` prevalue source type.
10+
11+
```csharp
12+
using System.Text.Json;
13+
using System.Text.Json.Serialization;
14+
using Umbraco.Cms.Core.Models;
15+
using Umbraco.Forms.Core;
16+
using Umbraco.Forms.Core.Attributes;
17+
using Umbraco.Forms.Core.Models;
18+
using Umbraco.UIBuilder.Configuration;
19+
using Umbraco.UIBuilder.Services;
20+
21+
namespace MyFormsExtensions
22+
{
23+
public class UIBuilderRepository : FieldPreValueSourceType
24+
{
25+
private readonly UIBuilderConfig _config;
26+
private readonly EntityService _entityService;
27+
28+
public UIBuilderRepository(
29+
UIBuilderConfig config,
30+
EntityService entityService)
31+
{
32+
Id = new Guid("ED56A31B-56FD-41EA-9D21-755750879D13");
33+
Name = "UI Builder Repository";
34+
Alias = "uiBuilderRepository";
35+
Description = "Use a UI Builder repository as a prevalue source.";
36+
Icon = "icon-file-cabinet";
37+
38+
_config = config;
39+
_entityService = entityService;
40+
}
41+
42+
[Setting("Source", Description = "Select the source section, collection and data view", View = "UiBuilder.PropertyEditorUi.EntityPicker.SectionConfiguration", IsMandatory = true, DisplayOrder = 10)]
43+
public virtual string Source { get; set; } = string.Empty;
44+
45+
public override Task<List<PreValue>> GetPreValuesAsync(Field? field, Form? form)
46+
{
47+
var result = new List<PreValue>();
48+
49+
UIBuilderSectionConfiguration? configuration = ParseSourceConfiguration();
50+
if (configuration != null)
51+
{
52+
if (!string.IsNullOrEmpty(configuration.Collection))
53+
{
54+
CollectionConfig collectionConfig = _config.Collections[configuration.Collection];
55+
IEnumerable<object> entities;
56+
57+
if (string.IsNullOrEmpty(configuration.DataView))
58+
{
59+
entities = _entityService.GetAllEntities(collectionConfig);
60+
}
61+
else
62+
{
63+
var allEntities = new List<object>();
64+
const int pageSize = 100;
65+
int pageNumber = 1;
66+
long totalPages = 0;
67+
68+
while (pageNumber == 1 || pageNumber <= totalPages)
69+
{
70+
PagedResult<object> pagedResult = _entityService.FindEntities(
71+
collectionConfig,
72+
pageNumber: pageNumber,
73+
pageSize: pageSize,
74+
dataViewAlias: configuration.DataView);
75+
76+
if (pagedResult.Items != null)
77+
{
78+
allEntities.AddRange(pagedResult.Items);
79+
}
80+
81+
if (pageNumber == 1)
82+
{
83+
totalPages = pagedResult.TotalPages;
84+
}
85+
86+
pageNumber++;
87+
}
88+
89+
entities = allEntities;
90+
}
91+
92+
foreach (var entity in entities)
93+
{
94+
var id = GetPropertyValue(collectionConfig.IdProperty, entity);
95+
var name = GetPropertyValue(collectionConfig.NameProperty, entity);
96+
97+
result.Add(new PreValue()
98+
{
99+
Id = id?.ToString() ?? string.Empty,
100+
Caption = name?.ToString() ?? string.Empty,
101+
Value = id?.ToString() ?? string.Empty
102+
});
103+
}
104+
}
105+
}
106+
107+
result = result.OrderBy(x => x.Id).ToList();
108+
return Task.FromResult(result);
109+
}
110+
111+
public override List<Exception> ValidateSettings()
112+
{
113+
var exceptions = new List<Exception>();
114+
115+
UIBuilderSectionConfiguration? configuration = ParseSourceConfiguration();
116+
if (configuration != null)
117+
{
118+
if (string.IsNullOrEmpty(configuration.Section))
119+
{
120+
exceptions.Add(new Exception("'Section' setting has not been set"));
121+
}
122+
123+
if (string.IsNullOrEmpty(configuration.Collection))
124+
{
125+
exceptions.Add(new Exception("'Collection' setting has not been set"));
126+
}
127+
}
128+
129+
return exceptions;
130+
}
131+
132+
private UIBuilderSectionConfiguration? ParseSourceConfiguration()
133+
{
134+
if (string.IsNullOrEmpty(Source))
135+
{
136+
return null;
137+
}
138+
139+
List<UIBuilderSectionConfigItem>? config = JsonSerializer.Deserialize<List<UIBuilderSectionConfigItem>>(Source);
140+
var result = new UIBuilderSectionConfiguration();
141+
142+
if (config != null)
143+
{
144+
foreach (UIBuilderSectionConfigItem item in config)
145+
{
146+
switch (item.Alias)
147+
{
148+
case "section":
149+
result.Section = item.Value;
150+
break;
151+
case "collection":
152+
result.Collection = item.Value;
153+
break;
154+
case "dataView":
155+
result.DataView = item.Value;
156+
break;
157+
case "labels":
158+
if (!string.IsNullOrEmpty(item.Value))
159+
{
160+
result.Labels = JsonSerializer.Deserialize<UIBuilderLabels>(item.Value);
161+
}
162+
break;
163+
}
164+
}
165+
}
166+
167+
return result;
168+
}
169+
170+
private static object? GetPropertyValue(PropertyConfig? propertyConfig, object entity)
171+
{
172+
if (propertyConfig == null)
173+
{
174+
return null;
175+
}
176+
177+
return propertyConfig.PropertyGetter?.Invoke(entity) ?? propertyConfig.PropertyExpression.Compile().DynamicInvoke(entity);
178+
}
179+
}
180+
181+
internal class UIBuilderSectionConfigItem
182+
{
183+
[JsonPropertyName("alias")]
184+
public string? Alias { get; set; }
185+
186+
[JsonPropertyName("value")]
187+
public string? Value { get; set; }
188+
}
189+
190+
internal class UIBuilderSectionConfiguration
191+
{
192+
public string? Section { get; set; }
193+
public string? Collection { get; set; }
194+
public string? DataView { get; set; }
195+
public UIBuilderLabels? Labels { get; set; }
196+
}
197+
198+
internal class UIBuilderLabels
199+
{
200+
[JsonPropertyName("plural")]
201+
public string? Plural { get; set; }
202+
203+
[JsonPropertyName("singular")]
204+
public string? Singular { get; set; }
205+
}
206+
}
207+
```
208+
209+
And registered with:
210+
211+
```csharp
212+
public class MyComposer : IComposer
213+
{
214+
public void Compose(IUmbracoBuilder builder)
215+
{
216+
builder.WithCollectionBuilder<FieldPreValueSourceCollectionBuilder>()
217+
.Add<UIBuilderRepository>();
218+
}
219+
}
220+
```
221+
222+
This will then make the **UI Builder Repository** available when creating a new prevalue source:
223+
224+
![UI Builder Repository available as a prevalue source](./images/uibuilder-repository-prevalue-source.png)
225+
226+
Once selected, you can pick a **Section**, **Collection**, and **Data View** from the configured UI Builder repositories:
227+
228+
![Selecting a UI Builder repository as a prevalue source](./images/uibuilder-repository-prevalue-configuration.png)

17/umbraco-forms/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
* [Adding A Field Type To Umbraco Forms](developer/extending/adding-a-fieldtype.md)
5151
* [Excluding a built-in field](developer/extending/excluding-a-built-in-field.md)
5252
* [Adding A Prevalue Source Type To Umbraco Forms](developer/extending/adding-a-prevaluesourcetype.md)
53+
* [Adding a UI Builder repository as a prevalue source](developer/extending/uibuilder-repository-prevalue.md)
5354
* [Adding A Workflow Type To Umbraco Forms](developer/extending/adding-a-workflowtype.md)
5455
* [Adding An Export Type To Umbraco Forms](developer/extending/adding-a-exporttype.md)
5556
* [Adding a Magic String Format Function](developer/extending/adding-a-magic-string-format-function.md)
60.6 KB
Loading
51.8 KB
Loading

0 commit comments

Comments
 (0)