A class can contain actions that are generally shown as buttons or links in a UI and run some code when pressed.
A build adds an action with Action()
, shown below.
Table of Contents | ||
---|---|---|
|
Eine Klasse kann verschiedene Aktionen beinhalten welche im Kontext der Entität ausgeführt werden können.
Die Konfiguration ist dabei analog einem normalen Property mit einigen zusätzlichen Möglichkeiten:
Zuweisen der Aktion die ausgeführt werden soll inklusive Rückgabewert
Definition wie die Aktion angezeigt werden soll (in Listen, Detail etc.)
Die Builder Methode sieht wie folgt aus:
Code Block |
---|
Builder.Add.Action(...) |
The action defined above doesn't do anything yet.
While a product can of course include code directly, it's strongly recommended to make some sort of method container that can be tested. The following example from the Sandbox passes the call to DeletePerson
to a _businessLogic
. The Result
is a hint to the caller so that it can update the UI.
Code Block |
---|
private void DeletePerson([NotNull] object sender, [NotNull] MetaActionEventArgs args)
{
if (sender is Person person)
{
_businessLogic.DeletePerson(person);
args.Result = MetaActionResult.CallingObjectChanged;
}
args.Result = MetaActionResult.None;
}
|
A product can attach code using the Body(...)
method.
Code Block |
---|
Builder.Add
.Action("DeletePerson")
.Body(DeletePerson) |
Actions with Parameters
Some action require more context than other to work properly.
For example the given action will require a “Contact” as a parameter:
Code Block | ||
---|---|---|
| ||
// Builder Elements.Person.Add.Action<Person, Contact>("AddContact", nameof(Elements.Contact), AddContactClassBuilder.Add.Action(...) |
Um einen Body zuzuweisen stehen folgende Overloads zur Verfügung:
Methode | Beschreibung |
---|---|
| Der |
| Der Diese Aktion ist hilfreich wenn eine Aktion z.B. auch auf einer Selektion von Objekten ausgeführt werden kann. |
| Direkte Zuweisung eines Delegate. Die Signatur der Methode muss dabei einen Parameter vom Typ |
| Der |
Die generische Methode um eine Aktion direkt mit den MetaActionEventArgs
auszuführen steht ebenfalls zur Verfügung. Es wird aber davon abgeraten diese zu verwenden. Die Abkapslung in Services erhöht die Testbarkeit der jeweiligen Aktionen und verhindert das Business-Logik direkt in die Builders geschrieben wird.
Jede Aktion kann definieren welche Änderungen sie vorgenommen hat und drückt diese über den Rückgabetyp aus.
Rückgabetyp | Beschreibung |
---|---|
| Keine Änderungen. Die Daten im Client werden nicht neu geladen. |
| Das aufgerufene Objekt muss neu geladen werden. |
| Das aufgerufene und alle verlinkten Objekte müssen neu geladen werden. |
Als optionaler Parameter kann bei allen Methoden folgendes definiert werden:
Parameter | Beschreibung |
---|---|
| Kann definieren ob die Aktion erfolgreich war:
|
| Meldung die dem Benutzer angezeigt wird. |
Soll zusätzlich zur Rückmeldung noch eine Navigation erfolgen so kann die Klasse NavigationLinkActionResult
verwendet werden. Der NavigationLinkAspect
muss dabei als Parameter zur Verfügung gestellt werden.
Aktionen auf Listen
Die oben beschriebenen Aktionen können auch auf Listen eingebunden werden. Dazu steht ein Overload zur Verfügung welcher eine Liste von Objekten zur Verfügung stellt. Dies kann hilfreich sein wenn eine Aktion z.B. auf eine Selektion von Objekten ausgeführt wird und nur ein Resultat erwartet wird.
Wird eine Aktion auf eine Liste von Objekten ausgeführt aber nur eine Methode unterstützt die Einzelobjekte behandelt so wird das letzte Resultat dem Client zurückgegeben und die restlichen verworfen.
Info |
---|
Wenn Aktionen auf mehreren Objekten ausgeführt werden können so wird empfohlen immer eine Liste von Objekten zu unterstützen. |
Aktionen mit Parameter
Einige Aktionen erfordern eine Eingabe um erfolgreich ausgeführt werden zu können.
Um eine Aktion mit Parametern auszustatten stehen dieselben Methoden wie oben beschrieben zur Verfügung mit der Ergänzung eines zusätzlichen Type-Argument welches den Parameter-Typ identifiziert.
Methode | Beschreibung |
---|---|
| Der |
| Direkte Zuweisung eines Delegate. Die Signatur der Methode muss dabei einen Parameter vom Typ |
| Der |
Der Parameter für die Aktion wird im Client über ein Popup abgefragt und danach an die entsprechende Aktion weitergeleitet. Es stehen dieselben Rückgabetypen wie bei einer normalen Aktion zur Verfügung.
Aktionen mit Bestätigung
Aktionen können optional eine Bestätigung des Benutzers einholen. Dies ist hilfreich wenn eine Aktion potentiell schwerwiegende Konsequenzen haben könnte.
Das folgende Snippet fragt nach der Bestätigung des Benutzers bevor die Aktion ausgeführt wird:
Code Block | ||
---|---|---|
| ||
builder.Get.Class(nameof(elements.Person)).Add.Action("TestActionWithConfirmation") .RequiresConfirmation() .Content(German, "Inhalt") .CaptionTitle(German, "Kontakt hinzufügen...Titel") .CaptionContinueCaption(EnglishGerman, "Add contact...Weiter"); // Method private void AddContact([NotNull] Person person, [NotNull] Contact contact, MetaActionExecutionContext executionContext) { if (person == null) { throw new ArgumentNullException(nameof(person)); } if (contact == null) { throw new ArgumentNullException(nameof(contact)); } person.Contacts.Add(contact); person.Save(); } |
This will lead to a popup once the action is invoked and the user will have to fill out the popup before being able to execute the action.
Actions with Confirmation
If an action wants to display a warning or hint before executing an action the following method can be used:
Code Block | ||
---|---|---|
| ||
builder.Get.Class(nameof(elements.Person)).Add.Action("TestActionWithConfirmation.CancelCaption(German, "Abbrechen"); |
Die Captions sind optional. Wird nichts angegeben werden die Standard-Übersetzungen verwendet.
Platzierung von Aktionen
Für die Platzierung von Aktionen in einer Listen- und Detail-Ansicht, es gibt drei Möglichkeiten:
Selektion-Aktion: Buttons, die erscheinen, wenn man mehrere Elemente in einer Liste angewählt hat.
Aktionen anzeigen in einer Liste bzw. in einer Reihe.
Aktion wird in einer Reihe neben dem Trash Button, über die drei punkte angezeigt und wird auf einem Klick aufgerufen.
Listen-Ansichten
Bei den Listen Ansichten - ListLayout kann man die Aktionen über die Methode SetListAction()
anhängen:
Code Block | ||
---|---|---|
| ||
SetListAction(
[NotNull] this T element,
bool showInListSelection = true,
bool showInListRow = true,
bool isOverflowByDefault = false) |
Code Block | ||
---|---|---|
| ||
list.Add.Link(metadata.Person.LowerCaseNameListAction)
.Element.SetListAction(true, true, true); |
Detail-Ansichten
Bei der Detailansicht - Detail Layout gib es ebenfalls drei Möglichkeiten um die Aktion zu platzieren:
Als eine Standard Aktion in der Sidebar.
In den Inhalt der Detail-Ansicht.
Es besteht die Möglichkeit ebenfalls die Aktion als primäre oder sekundäre Aktion anzuzeigen.
Eine Standard-Aktion in der Sidebar zu implementieren, muss folgendes Vorgehen eingehalten werden:
1. Es wird eine Variable als Aktionen deklariert und wird und die Sidebar Funktion wird dem Layout angehängt.
Code Block |
---|
var sidebar = elements.Person.Add.Sidebar() |
1.1 Anschliessend wird der Sidebar eine Aktion angehängt und über die Add. Action Methode die entsprechende Aktion aufgerufen.
Code Block |
---|
var actions = sidebar.Add.Actions();
actions.Add.Action(metadata.Person.LowerCaseNameDetailAction); |
1.2 Um eine Aktion in dem Detail Ansicht Inhalt platzieren zu können, muss man folgendes implementieren, im folgenden Beispiel werden wir die Aktion in einer Reihe integrieren:
Code Block |
---|
row.Add.Link(metadata.Person.LowerCaseNameDetailAction); |
In dem beiden Fällen ist es möglich die Art die Aktion zu steuern, ob es sich um eine primäre Aktion oder als eine sekundäre Aktion handelt. Die Methode IsClassAction beinhaltet drei Parameter, durch die die Optionen der Aktion gesteuert werden können.showAsMainAction
: Zeige es an als eine HauptaktionshowAtStartOfGroup
: Zeige es am Anfang der Gruppe von den AktionenisPrimary:
Ist es eine primäre Aktion, hierdurch wird das Styling der Aktion geändert.
Code Block |
---|
bool showAsMainAction = false,
bool showAtStartOfGroup = false,
bool isPrimary = false) |
Code Block |
---|
Elements.Controls.Add.Action("SampleAction").IsClassAction(true, true, true) |
Die SampleAction ist in diesem Beispiel eine Hauptaktion, ist die erste Aktion in der Gruppe von Aktionen, und ist eine primäre Aktion, hierdurch wird das Styling angepasst.
Berechtigungen
Aktionen können grundsätzlich nur von authentifizierten Usern ausgeführt werden. Die Ausnahme bilden Aktionen die im Client direkt implementiert sind.
Standardmässig benötigt der User Lese-Berechtigung auf der Klasse auf welcher die Aktion sich befindet. Nur dann ist eine Ausführung möglich. Diese Restriktion kann pro Aktion angepasst werden um zu verhindern das Aktionen ausgeführt werden die Daten verändern:
Code Block |
---|
Elements.Person.Add.Action("SampleAction") .RequiresConfirmationPermissionRequired(GenericOperation.Create); |
Eine so definierte Aktion kann nur von einem User ausgeführt werden welcher über “Create” Berechtigung auf der Entität verfügt.
Erweiterte Einschränkungen zur Ausführung können über den optionalen Parameter “expression” gemacht werden. Dieser erlaubt es eine Expression zu definieren welche evaluiert wird und die Ausführung verhindert wenn diese nicht auf “true” evaluiert.
Code Block |
---|
.Content(German, "InhaltElements.Person.Add.Action("SampleAction") .TitlePermissionRequired(GermanGenericOperation.Create, "Titel")Aktiv == true"); |
Die beiden Permission Möglichkeiten lassen sich auch kombinieren. In diesem Falle muss der User sowohl die Berechtigung auf die Entität haben als auch die Expression erfüllt sein.
Code Block |
---|
.ContinueCaption(German, "WeiterElements.Person.Add.Action("SampleAction") .CancelCaption(German, "Abbrechen"); |
Die Captions für die einzelnen Bereich können dabei auch leer gelassen werden um die Standardübersetzungen zu verwenden.
Placement of actions in a List
If an action is added to a list via LinkAction
the placement can be controlled with the following options:
Code Block |
---|
list.Add.LinkAction(metadata.Person.LowerCaseNameListAction).ShowInListSelection().IsOverflowByDefault();
list.Add.LinkAction(metadata.Person.UpperCaseNameListAction).ShowInListRow(); |
Placement of actions in a Detail
If an action is added directly to a detail layout the action will be displayed in the sidebar
Code Block |
---|
detail.Add.LinkAction(metadata.Person.LowerCaseNameListAction);
detail.Add.LinkAction(metadata.Person.UpperCaseNameListAction); |
To show an action in a layout add it to the parent element e.g a group:
Code Block |
---|
group.Add.LinkAction(metadata.Person.LowerCaseNameDetailAction); |
...
PermissionRequired("Aktiv == true"); |
Bei der Ausführung auf einer Klasse ohne spezifisches Objekt wird die Expression ebenfalls evaluiert. Kann diese nicht evaluiert werden wird ein entsprechender Log-Eintrag generiert und die Aktion trotzdem ausgeführt.
Die Ausführung auf einer Liste wird die Expression für alle Entitäten evaluieren und nur diejenigen ausführen die ein gültiges Resultat liefern. Dem Benutzer wird eine entsprechender Fehler angezeigt falls nur ein Teil der Aktionen ausgeführt werden konnte.
Erweiterte Restriktionen die nicht über Expressions oder die Berechtigungen modelliert werden können müssen in der Aktion selbst implementiert werden.
Resultate
Das Resultat einer Aktion ist grundsätzlich frei wählbar. Standardmässig werden aber die MetaActionResult
unterstützt und vom Client interpretiert.
Damit das zusammenstellen dieses Resultat etwas einfacher ist kann der MetaActionResultBuilder
verwendet werden.
Code Block | ||
---|---|---|
| ||
var result = MetaActionResult.Builder()
.WithChanges(MetaActionChanges.CallingObject)
.WithAbsoluteNavigation("https://encodo.ch", OpenInTarget.Popup)
.WithFeedback(MetaActionFeedbackType.Warning, new DynamicString(("en", "Custom Message")))
.Build(); |
Dies produziert ein Resultat welches zur angegebenen Website navigiert.
Es stehen weitere Signaturen für eine Objekt-Navigation und Klassen-Navigation (Liste) zur Verfügung. Auch kann übersteuert werden welche Objekte sich geändert haben und was für ein Feedback genau gegeben werden soll.