Snk.Net.Blazor
10.4.0
dotnet add package Snk.Net.Blazor --version 10.4.0
NuGet\Install-Package Snk.Net.Blazor -Version 10.4.0
<PackageReference Include="Snk.Net.Blazor" Version="10.4.0" />
<PackageVersion Include="Snk.Net.Blazor" Version="10.4.0" />
<PackageReference Include="Snk.Net.Blazor" />
paket add Snk.Net.Blazor --version 10.4.0
#r "nuget: Snk.Net.Blazor, 10.4.0"
#:package Snk.Net.Blazor@10.4.0
#addin nuget:?package=Snk.Net.Blazor&version=10.4.0
#tool nuget:?package=Snk.Net.Blazor&version=10.4.0
Snk.Net.Blazor
SNK .NET Blazor Library - Blazor components and services for SNK .NET applications.
Installation
dotnet add package Snk.Net.Blazor
Requirements
- .NET 10.0 or later
- Blazor WebAssembly
Forms: SnkFormView
SnkFormView (namespace Snk.Net.Blazor.Forms) renders a Snk.Net.Forms definition
with the SNK input controls and edits its FormAnswers in place. The rules are re-applied on every change, so
fields appear, disappear and become required as the user types.
@using Snk.Net.Blazor.Forms
@using Snk.Net.Forms
<SnkFormView @ref="_form" Definition="_definition" @bind-Answers="_answers"
ReadOnly="_submitted" SignerName="@_user.Name"
OnAttachmentRequested="UploadAsync" />
<button class="btn btn-primary" @onclick="SubmitAsync">Submit</button>
@code {
private SnkFormView _form = default!;
private FormDefinition _definition = FormJson.DeserializeDefinition(json);
private FormAnswers? _answers; // null = a blank set with the defaults is created and bound back
private async Task SubmitAsync()
{
var result = await _form.ValidateAsync(); // errors under the fields, first one scrolled to and focused
if (result.IsValid) await Save(FormJson.Serialize(_answers!));
}
private async Task UploadAsync(SnkAttachmentRequest request)
{
var stored = await MyUploader.PickAndUploadAsync(request.FileTypes, request.Remaining);
foreach (var file in stored) await request.AddAsync(new FileRef(file.Id, file.Name, file.Type, file.Size, file.Url));
}
}
| Parameter | Meaning |
|---|---|
Definition, Answers / AnswersChanged |
The form and its answers (edited in place; AnswersChanged fires after every change). |
ReadOnly |
Every field read-only. A field's own readOnly always applies. |
Registry |
The engine's FieldTypeRegistry (validation, defaults); null = the built-ins. |
FieldRenderers |
SnkFieldRenderers for app types - also overrides a built-in key. |
Now, SignerName |
The clock for settings.timestamp choices; the signedBy of a signature. |
OnAttachmentRequested, OnFieldChanged |
"Add file" pressed; a value changed (rules already applied). |
FieldWrapper |
Optional chrome around each field (SnkFieldWrapperContext.Content) - the seam a designer canvas uses. |
SectionWrapper |
Optional chrome around each section (SnkSectionWrapperContext: section, Visible, Content). |
DesignMode |
Render every section and field, even the ones the rules hide (the wrappers see Visible = false). For a designer canvas only. |
Methods: Validate(), ValidateAsync(), ClearErrors(), SetAnswerAsync(path, value),
AddAttachmentAsync(path, file); State and LastValidation expose the evaluated state and errors.
How each type is drawn
| Type | Control |
|---|---|
text, email, phone |
SnkTextBox (text / email / tel), maxLength applied |
number |
SnkTextBox<decimal?> (number) |
textarea |
SnkTextArea |
date / datetime / time |
SnkTextBox with the browser's native picker - SnkTextBox<DateOnly?> (date), SnkTextBox<DateTime?> (datetime-local), SnkTextBox<TimeOnly?> (time); owner decision 2026-09-21, a deliberate exception to "date → SnkCalendar" elsewhere in the app. A datetime is written with the browser's offset, or as a wall-clock value when the field sets settings.localTime |
dropdown |
SnkDropDown, or SnkMultiSelectDropDown with settings.multiple |
radio / checklist / checkbox |
SnkRadioButtonList / SnkCheckBoxList / SnkCheckBox; settings.layout (vertical / horizontal) sets the list's orientation - a radio list is horizontal and a check list vertical without it, and a horizontal list wraps and stacks on a phone |
attachments |
A file list and an "Add file" button raising OnAttachmentRequested (SnkFileUpload posts to the app's upload API and binds FileUploadInfo, not the engine's FileRef answer) |
signature |
A canvas pad; "Accept" stores { data: PNG data URI, signedBy, signedAt } |
table |
One card per row, cells drawn by the same field rendering; add/remove within minRows/maxRows, fixed with settings.fixedRows |
heading, paragraph, divider |
Display only; a paragraph's settings.linkUrl (http/https) becomes a link |
| anything unrendered | A read-only notice; the answer is kept |
The SNK controls render their own floating label, required marker, help text and error - the form adds no
<label>. Width full / half / third / quarter maps to col-12 / col-md-6 / col-md-4 /
col-md-6 col-lg-3, so fields stack on a phone (quarter stays two-up until lg).
Styling is Bootstrap plus the library theme (light and dark), icons are Font Awesome.
App field types
Register the type with the engine (validation) and a renderer with the view:
var registry = FieldTypeRegistry.CreateDefault()
.Register(new ChoiceFieldType("users", multiple: true, optionsFromDefinition: false));
var renderers = new SnkFieldRenderers()
// a data-driven picker drawn like the built-in choice fields
.RegisterChoice("users", SnkChoiceStyle.Dropdown, ctx => users.Select(u => new FieldOption(u.Id, u.Name)).ToList())
// or a component with [Parameter] FieldRenderContext FieldContext (or a RenderFragment<FieldRenderContext>)
.Register<ShiftPicker>("shift");
Inside a renderer, FieldRenderContext carries the field, Value, Required, ReadOnly, Errors and
SetValueAsync. To bind an SNK control so it shows the required marker and errors itself, use Bind:
@{ var b = ctx.Bind<string>(v => FormAnswerValues.ReadText(v) ?? "", FormAnswerValues.WriteText); }
<SnkTextBox TValue="string" Value="b.Value" ValueChanged="b.ValueChanged" ValueExpression="b.ValueExpression" Label="@ctx.Label" />
For plain markup, SnkFieldCaption and SnkFieldFeedback draw the caption and the errors the same way the
built-in composite fields do.
Forms: SnkFormDesigner
SnkFormDesigner (namespace Snk.Net.Blazor.Forms) lets people who do not write code build a
Snk.Net.Forms definition. It replaces the app-side jQuery formbuilder.js builder.
<SnkFormDesigner @bind-Definition="_definition"
Registry="_registry" FieldRenderers="_renderers"
CustomFieldTypes="_custom"
OnSave="SaveAsync" />
@code {
private FormDefinition? _definition; // null = a new form with one section
private readonly FieldTypeRegistry _registry = FieldTypeRegistry.CreateDefault()
.Register(new ChoiceFieldType("inspector", multiple: false, optionsFromDefinition: false));
private readonly SnkFieldRenderers _renderers = new SnkFieldRenderers()
.RegisterChoice("inspector", SnkChoiceStyle.Dropdown, _ => Staff());
private readonly IReadOnlyList<SnkPaletteItem> _custom =
[new("inspector", "Inspector", "fa-solid fa-user-check", "Airport")];
private Task SaveAsync(FormDefinition form) => Api.SaveFormAsync(FormJson.Serialize(form));
}
| Parameter | Meaning |
|---|---|
Definition / DefinitionChanged |
The form, edited in place. Undo/redo swap in a NEW instance, so use @bind-Definition. |
Registry, FieldRenderers |
The same objects the app gives SnkFormView (issues, canvas and preview use them). |
CustomFieldTypes |
SnkPaletteItem(type, label, icon, group) entries for the app's own types; Initialize can seed a new field. |
OnSave |
Shows a Save button, disabled while the form has errors; receives the definition. |
ReadOnly |
Inspect only: no palette, drag or edit commands, disabled property editors. |
What the user gets:
- Palette (left): the built-in types grouped Basic / Choice / Date & time / Media / Layout, then the app's groups, with a search box. Click an entry to add it after the selected field, or drag it to where it should go. Choice fields start with two options, a table with one column, so a new field is never born broken.
- Canvas (centre): the real
SnkFormView(DesignMode,FieldWrapper,SectionWrapper). Click a field or section to select it; drag its grip to move it (a dropped item takes the place of the field it lands on; drop on a section's "drop here" zone to append). The selected field shows move up / down, duplicate and delete buttons - the keyboard and touch path for every drag. Fields a rule hides are shown dimmed with a badge. - Properties (right): label, id (renamed through
FormDesigner.RenameId, so the rules follow; invalid or taken ids are refused), help, placeholder, width, layout (vertical / horizontal, for a field that lists its options), required, read-only, default value, options (add, reorder, remove, paste one per line), validation for the type (length and pattern, min / max, choose at least / at most, file types / count / size) and type settings (multiple,timestamp,localTime, paragraph links, tableminRows/maxRows/fixedRowsand pre-filled rows). A table's columns are listed there and edited with the same panel. - Rules tab: every rule as a sentence ("When Surface condition is Poor, show Defects; make required Remarks."), with a builder - field, operator in plain words, a value picker that offers the source field's options, all / any, then show / hide / make required / make optional on any fields or sections. Rules can be reordered (the later one wins). A rule's problems are shown under it.
- Problems tab:
DefinitionValidator's issues; click one to go to the field, column, section or rule. - Undo / Redo (whole-definition snapshots, 50 deep) and Preview: the plain interactive form with its answers JSON and the definition JSON.
Below lg the three panes become one at a time behind an Add / Form / Properties switch. Styling is Bootstrap
plus css/components/snk-form-designer.css (theme variables only, light and dark); icons are Font Awesome;
every editor is an SNK input with its own floating label.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Blazored.LocalStorage (>= 4.5.0)
- Microsoft.AspNetCore.Components.Authorization (>= 10.0.12)
- Microsoft.AspNetCore.Components.Web (>= 10.0.12)
- Microsoft.Extensions.Http (>= 10.0.12)
- QRCoder (>= 1.6.0)
- Snk.Net.Forms (>= 10.4.0)
- Snk.Net.Shared (>= 10.4.0)
- System.IdentityModel.Tokens.Jwt (>= 8.22.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.