How to make a Input field in AEM/CRX required? - input

since our AEM guy is out of office at the moment, i need to fix something in our CRX. I have a form with a checkbox in my website, where authors can set a text next to it. Now i am trying to add the functionality to set this checkbox to be required from the authoring dialog.
I was able to find a textfield which has this property in authoring, but in the html in CRX i only see the code required=${required}, where other fields like label are shown like ${properties.label} and have a corresponding node in CRX. I don't understand how the required is implemented and need help here.
I already tried to add required=${required} to my checkbox input markup, but this did not work, since in the authoring dialog there still was no checkbox/switch to make the field required (which was kinda expected).
this is the line in the markup which should be required if the author sets it to required in the authoring dialog:
<input required="${required}" type="checkbox" name="campaignform-termsofservice"/>
this is the whole html of the checkbox i want to be able to make required:
<div data-sly-test="${!empty}" class="form__text">
<label class="maut-checkbox--container">
<input required="${required}" type="checkbox" name="campaignform-termsofservice"/>
<span class="maut-checkbox--checkmark"></span>
<span>${properties.checkboxtext #context='html'}</span>
<div>${properties.tncText}</div>
<div style="color:white;" class="authoring-error" data-sly-test="${wcmmode.edit && !tncDate.tncLinkActivationDate}">${'b2x.maut.campaignform.dialog.tos.activationmessage' # i18n, source='user'}</div>
<input type="hidden" name="maut.field.tnc" value="${tncDate.tncLinkActivationDate}" />
</label>
</div>
Now i only need to figure out how i can show the option to set it to required in the authoring dialog.
Thanks in advance

If you want to know how the required=${required} is implemented then first of all in html of the component look for something like data-sly-use.required. This will have a expression like =com.project.yourProject.className or some js file.
Lets discuss about the java case which is the most common way. What data-sly-use does is that it creates an object of the class that you gave in the expression. In your case your object is required. Then you need to check the java class that the expression evaluates to. Commonly all the backend logic code will be their and if some manipulations or validations are required to be done with the data that the author enters in the dialog will be their. This class will also contain annotations that maps the class variables with the property value of the dialog.
Hope this explains from where this ${required} came from. It will be more clear to you if you look into the java class that is referred to by the data-sly-use expression.

Related

How do I mix custom and standard error messages in validations on one form field

I am a beginner with Vuelidate and just completed the Easy Form Validation with Vuelidate video on YouTube. I followed the video carefully and everything seemed to go okay but I've run into a bit of trouble after trying to extend the concepts. I can't find a relevant insight in the Vuelidate docs.
I don't like the default message that appears when the confirm password doesn't match the first password supplied, so I want to provide my own custom message for it but the default messages are fine when the confirm password is not supplied at all or the confirm password is too short. I've written the code as follows and don't see an obvious mistake but when I actually test the code in the browser, I find that it ALWAYS gives me the custom message, even if the required or minLength validations are the ones that are failing. Why is that, and how must I write my code differently to work as intended?
<p>
<input type="password" placeholder="Confirm Password"
v-model="state.password.confirm"/>
<span class="error" v-if="v$.password.confirm.$error">
<span v-if="v$.password.confirm.required | v$.password.confirm.minLength">
{{v$.password.confirm.$errors[0].$message}}
</span>
<span v-else>
{{"Confirm password must match password on previous line"}}
</span>
</span>
</p>
Is it the "or" (|) in the v-if that is the problem? I thought a vertical bar (for "or") or an ampersand (for "and") were allowable in Vue but I may be confusing it with another language. I've just searched for an example containing a vertical bar or ampersand without success; all the examples I found use a single condition but I'm not sure if that's to keep things simple or because v-if can't handle more than one condition.
I'm using Vue3 and VSCode as my IDE.

Angular 2 - display one component as drop down in another and grabbing the selected value in parent component

This is my very first Angular 2 project. I created a component (category) that would pull a list of categories from a service stack API and show as a dropdown like this:
<select (change)="onSelect($event.target.value)" [(ngModel)]="selectedCategory.Id">
<option *ngFor="let category of categoriesToDisplay"
value={{category.Id}}>{{category.Name}}
</option>
</select>
Selected Category is: {{selectedCategory.Id}} and Name is {{selectedCategory.Name}}
I have another component (AddExpense) which is a form, where the user can add in the amount, category and hit submit that would POST to another endpoint. For AddExpense component, this is how the .html looks
<form [formGroup]="expense" (ngSubmit)="fileExpense($event)">
Spent <input type="number" formControlName="amt" />
for <input type="text" formControlName="name" />
on <input type="date" formControlName="transdate" />
and file it under category <show-category></show-category>
<button type="submit">Add Expense</button>
</form>
My question is how do I figure out which category from the drop down was selected in the add expense form, when the drop down itself is rendered via the show-category component and pass it on as a form control item for add-expense component's .ts to use?
I might be needing to use the Input and output decorator, but not sure how to nab that particular item thats selected in the dropdown and pass it on as input to the add expense component.
Sounds like you're displaying your first component (ShowCategory) in the second (AddExpense).
Now there is a couple way to do this,
The most obvious is to use Output, ShowCategory will then emit (See EventEmitter and Output example) whenever the selected value is changed.
In the template of AddExpense, you'd simply have to write something like this,
<show-category (change)="category = $event.category"></show-category>
But that's ugly, and frankly it would've been cool if we can do this and let Angular handle the two-way binding,
<show-category [(ngModel)]="category"></show-category>
Turns out it's doable, you can check out documentation for NgModel here, but what's actually useful is an example implementation for a real control like a checkbox
You might've noticed in the example that NgModel is not mentioned anywhere, and that's because we only have to create the mechanism for NgModel to write/read value from your component.
If you search on Google for NgModel ValueAccessor, there's a bunch of blog posts to help you out.
Lastly, I personally doesn't suggest doing what you're doing now if the ShowCategory component is that simple, that increases complexity a little bit, and ShowCategory isn't doing much for now. But what you provided might very well be a minimum working example, so what do I know.
Happy coding!

What is the advantage of using Tag Helpers in ASP.NET Core MVC

I just come across a good write up for a new ASP.NET Core feature called Tag helpers.
From there, I understood that one can replace the following code:
#model MyProject.Models.Product
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => p.Name, "Name:")
#Html.TextBoxFor(m => p.Name)
</div>
<input type="submit" value="Create" />
}
with:
#model MyProject.Models.Product
#addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
<form asp-controller="Products" asp-action="Create" method="post">
<div>
<label asp-for="Name">Name:</label>
<input asp-for="Name" />
</div>
<input type="submit" value="Save" />
</form>
There's some new syntax such as asp-controller, asp-for, etc. But what does it do? And what's the advantage of this new approach?
The most important improvement I've seen so far is the control it guarantees over your HTML elements. While convenient, the Html helpers used by MVC create problems when you try to do things they weren't built for.
A simple example can be seen when using the TextBox in MVC5:
#Html.TextBoxFor(m => p.Name)
The resulting HTML markup looks like:
<input class="form-control" id="Name" name="Name" type="text" value="">
Nice and simple. But what if you want to add a placeholder attribute? What if you want to use bootstrap's validation states? What if you have some 3rd party super cool javascript library which needs custom attributes. None of these things were possible in the initial release of MVC5. Though they were eventually added via update in the form of htmlAttributes. Even now adding custom attributes is kludgey at best.
#Html.TextBoxFor(m => p.Name,
new {#class="form-control has-error", placeholder="Enter Name",
superCoolFeature="Do something cool"})
While you could argue this is still less code that straight HTML, it is no longer a significant advantage. Worse, this solution still doesn't cover dashes in attributes which are fairly common. If you need them you are stuck with a workaround such as ActionLink htmlAttributes
I've gone down the route of fixing these deficiencies with custom editors, and tried building my own TextBox controls. It became obvious pretty quickly that replacing the included TextBox templates would require a lot of work. Worse, your templates have to have knowledge of any extensions you are adding to use them.
It seems like the inclusion of Bootstrap and other 3rd party tools into MVC have made it more obvious that the current design has problems with extending HTML which need to be fixed. Hopefully the tag helpers implementation is complete enough that we can avoid them in the future.
Not to mention, your Web Designers will have real HTML tags to edit that they recognize to re-design your pages. Designers shouldn't have to be coders and there's enough for these sharp folks to keep up with, studying the moving targets of HTML5 and CSS3 specs.
A few things come to mind:
As #ChrisWalter points out, these tag helpers give HTML tags an Open/Closed quality. Rather than just letting you write extension methods for common HTML patterns, you can extend an HTML element. This lets you pick-and-mix multiple extensions per component, rather than having to choose between them.
HTML Helpers tend to not work super well for elements that need to have inner HTML provided as an argument. They came up with a clever pattern so you can say:
#using (Html.BeginForm(...)){
{
<input ... />
}
But there's nothing about BeginForm() that would force you to put it in a using statement, and there's nothing to prevent you from using incorrect HTML structure. (<input> technically isn't allowed to be directly inside a <form> tag.)
This gives us a really easy transitional stepping stone into the Web Components world of HTML5. A component that you write today for jQuery or Bootstrap to pick up and enhance may make more sense as an Angular 2 or Polymer component in a few years. Using HTML syntax makes it possible to write your HTML the way you want it to look when it's a web component, and have it automatically translated into the structure it has to take on for now (or for specific browsers, later).
Accepted answer is correct but just a correction.
Html Helpers cover dashes in attributes by use of underscore. for example if you want html like
my-attr=value
then you can use html helpers like
#Html.TextBoxFor(m=>m.id,
new { my_attr = value })
then it will convert accordingly.
I know the original question asks about advantages but for the sake of completeness I have to mention one disadvantage:
With tag-helpers enabled you cannot inject C# code inside tag attributes.
I.e. this code will break:
<!-- this won't work -->
<input class="#GetMyClass()">
<!-- this won't work too -->
<input type="checkbox" #(condition ? "checked" : "") >
To work around this problem you can use custom tag helpers or just disable tag helpers altogether like described in this answer: https://stackoverflow.com/a/65281018/56621
P.S. My humble opinion that can be safely ignored: tag helpers are "magic". And "magic" is always bad in programming. If something looks like an HTML tag, walks like a tag and quacks like a tag - then it should probably be an HTML tag. Without me knowning "oh, it's not *really* a tag".
From building a basic web app from the ground up in .NET 7/Razor pages, I haven't encountered a single instance where a tag helper has an advantage over simply coding the HTML. I don't come from an MVC background so maybe that is where the advantage lies but as seen before...Microsoft has released yet another version of wheel-reinvention that instead of making things easier for some simply adds more confusion to others.

Work around to POST requirement

I need to be able give users a link to my site with a parameter that will control their experience on the destination page, but, of course, Moqui does not allow parameters to be passed as a GET transaction. What are ways that I can work around that? It needs to be something that can be sent in an email, via sms and audibly.
An error message would be helpful know exactly what you are running into, but it sounds like the constraint to mitigate XSRF attacks.
The error message for this situation explains the issue and the recommended solution: "Cannot run screen transition with actions from non-secure request or with URL parameters for security reasons (they are not encrypted and need to be for data protection and source validation). Change the link this came from to be a form with hidden input fields instead."
You can pass URL parameters to screens to be used in code that prepares data for presentation, but not to transitions for code that processes input. The solution is to use a hidden form with a link or button to submit the form (that can be styled as a link or button or however you want). This is slightly more HTML than a plain hyperlink with URL parameters, but not a lot more and there are examples in various places in the Moqui itself.
If you are using an XML Screen/Form you can use the link element to do this with the #link-type attribute set to "hidden-form" or "hidden-form-link" (which just uses a hyperlink styled widget instead of a button styled one). If the #link-type attribute is set to "auto" (which is the default) it will use a hidden-form automatically if link goes to a transition with actions.
In plain HTML one possible approach looks something like this:
<button type="submit" form="UserGroupMemberList_removeLink_0">Remove</button>
<form method="post" action=".../EditUserGroups/removeGroup" name="UserGroupMemberList_removeLink_0">
<input type="hidden" name="partyId" value="EX_JOHN_DOE">
<input type="hidden" name="userGroupId" value="ADMIN">
</form>
Note that the button element refers to the form to submit, so can be placed anywhere in the HTML file and the form element can be placed at the end or anywhere that is out of the way (to avoid issues with nested forms which are not allowed in HTML).

(dojo) dojox.form.Manager not firing observers

I have a customer dialog widget that I am attempting to use dojox.form.Manager on.
I have just stumbled across this control and it looks to do most of what I was implementing (unified onchange events) but much more. There is just one problem, the observer events will not fire.
I have a form element containing multiple digits, form, and custom widgets. Each is set up something like
<form id="resd_tab_details"dojoType="dojox.form.Manager">
<input type="checkbox" dojoType="dijit.form.CheckBox" name="w01" value="w01"
observer="testfunction1">
</form>
I can attach to the form set values and everything else I have tried, except the events.
What might I be doing wrong?
IIRC an observer is a method name on a form manager, not a standalone function. While you didn't give the complete example to test, your naming suggest that you use a standalone function.
You can define a method on the form manager either inline (see an example in its "tests" subdirectory), or in the code by subclassing a manager.
like this...
js portion
dojo.mixin(dijit.byId('frmMngr1'), {
'prvUpdate':function(){
console.log("clicked a check box");
}
})
html portion:
<form dojoType='dojox.form.Manager' id='frmMngr1'><input dojoType='dijit.form.CheckBox' observer='prvUpdate' checked name='title' />