Aurelia and Kendo - kendo-ui

When using Kendo with AngularJS, it is possible (maybe preferred) to configure the components in your javascript via the k-options attribute
<input kendo-date-picker k-options="monthPickerConfig">
However with Aurelia it seems that the configuration is only available in the markup.
<input style="width: 100%;"
ak-datetimepicker="k-value.two-way: today;
k-widget.two-way: startDatePicker;
k-parse-formats.bind: ['MM/dd/yyyy']"
k-on-change.delegate="startChange()"/>
Is my understanding here correct, or is there a way to configure the widets via javascript?

Using the Aurelia KendoUI Bridge wrapper, indeed the most documented way is configuring your Kendo components through the view. Like you mentioned something like:
<input id="monthpicker"
ak-datepicker="k-value.bind:'November 2011';
k-start.bind:'year';
k-depth.bind: 'year';
k-format.bind:'MMMM yyyy';"
style="width: 100%" />
But I believe there is nothing stopping you from referencing this element in your view<>viewmodel:
<!-- simplified -->
<input id="monthpicker" view-model.ref="mypicker" />
... so you can configure it completely in your viewmodel:
import 'kendo-ui/js/kendo.combobox';
export class App {
private mypicker: kendo.ui.DatePicker;
attached() {
this.mypicker... // <-- set your config/options for Kendo here...
}
}
Might be an alternative, right?

Related

How to pass ViewModels into Razor Components in .NET Core 3.1

I have a View MyView.cshtml with the following content:
#using MyProject.ViewModels
#model MyProject.ViewModels.MyViewViewModel
<form asp-action="Test" method="Post">
<component type="typeof(MyProject.Views.Home.Test)" render-mode="ServerPrerendered" />
<input type="submit" value="send"/>
</form>
And I have the Razor Component Test.razor with the following content (with Blazor Syntax):
#page "/Test"
<div class="form-group top-buffer #Visible">
<div class="row">
<div class="col-2">
<label asp-for="TestName" class="control-label"></label>
</div>
<div class="col-3">
<input asp-for="TestName" class="form-control" />
<span asp-validation-for="TestName" class="text-danger"></span>
</div>
</div>
</div>
<button #onclick="Show">Show</button>
#code {
public string Visible { get; set; } = "hidden";
protected async Task Show()
{
Visible = "";
}
}
The Class MyViewViewModel would look like this:
namespace MyProject.ViewModels
{
public class MyViewViewModel
{
[Display(Name = "Test Name:")]
public string TestName { get; set; }
}
}
Works all pretty fine so far. However I now want to use this component as part of a Web form which will be sent to the controller after submission. That's why I need to access and change properties of my ViewModel 'MyViewViewModel'. Unfortunately I did not find any answer in the internet on how to do that. I can't use #model MyProject.ViewModels.MyViewViewModel like in the view because this will give me a compilation error. I wonder if I need to use #inject, but if yes, I don't know how...
(parts are used from this example: https://jonhilton.net/use-blazor-in-existing-app/)
When you mix Blazor in a Razor Page, you can do the following:
Render a Razor Component
Interact with a Razor Component
Pass a Razor Component values
Please keep in mind that you are dealing with two different life-cycles. So if you do work inside of a Razor Component, the component will update but not effect the Razor Page it is hosted inside of. So mixing Razor Components and Pages with forms would be difficult.
More specifically to the OP. To pass data from your ViewModel to the component you may use the following method.
#using MyProject.ViewModels
#model MyProject.ViewModels.MyViewViewModel
<form asp-action="Test" method="Post">
<component type="typeof(MyProject.Views.Home.Test)"
render-mode="ServerPrerendered"
param-Name="#Model.TestName"/>
<input type="submit" value="send"/>
</form>
Test.razor
<h3>HelloWorld</h3>
Hello #Name
#code {
[Parameter]
public string Name { get; set; } = "undefined";
}
About life cycles
Basically when you have a button in Blazor, it will trigger an event which causes the component to re-render. You could imagine it like an iframe, or update-panel. When you have a button in a Razor page, it does a HTTP call round trip and reloads the page entirely. There is no event system in place to tell Blazor to invoke an HTTP call round trip to refresh the Razor page's content and vise versa. You can only one-way data-bind from Razor pages to Blazor, think write-only, and only when the page loads.
To hopefully add to the info. With a ASP.Net Core MVC project host Blazor webassembly, I was trying to pass a viewmodel into a razor component using this code in my view cshtml file:
<component Type="typeof(Leave)" render-mode="WebAssembly" model="new { model = (MyViewModel)#Model})"/>
But it would fail to render the razor component if I tried to access data in the viewmodel from the razor component with an Object not set exception. I think it was accessing the data before the view model has been initialized. Maybe if I set a default value this could avoided?
I found by using this instead I was able to get it working.
#(await Html.RenderComponentAsync<Leave>(RenderMode.WebAssembly,new { model = (MyViewModel)#Model}))
Edit
Seems you also need to register the viewModel class in the services in the Blazor WASM project in the Program.cs file.
builder.Services.AddScoped(sp => new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<MyViewModel,MyViewModel>(); // <= add this line
await builder.Build().RunAsync();`
Without that I would get an error saying the property could not be found.
Hopefully this saves someone else some time :-)

UWP get form in webviewer returning 'about:blank' rather than form values

We have a mobile app which shows an html page with some javascript in a webviewer.
In this page we have a form. IT looks something like:
<form method="get" action = "" id="mainform">
<input name="EXAMPLE_NAME" id"EXAMPLE_NAME" placeholder="" type="text" maxlength="35"/>
</form>
So far so good. The user is able to view this input and fill it in with data. They then press a button on the xaml page which calls a function that does:
Browser.Eval("submitMainForm()")
In the javascript on the page we have that function, which looks like:
function submitMainForm() {
var x = document.getElementById("mainForm").submit();
}
Back in the C# code we have handlers for the resulting navigation. They look like:
async void OnNavigating(object sender, WebNavigatingEventArgs e)
{
and
void OnNavigated(object sender, WebNavigatedEventArgs e)
{
This works well in iOS and Android. We get the WebNavigatingEventArgs in the handler, and the value from the field that we are showing in the webviewer (inside of mainform) are stored in there.
So, for example, e.Url in the OnNavigating and OnNavigated handlers would look something like:
"file:///storage/emulated/0/Android/data/com.example.exampleapp/files/Example.html?EXAMPLE_NAME=Test"
We parse this string to get the values we care about (Test, in this case), and all is well.
On UWP, however, things work a lot less well. On Navigating is never called at all, and the call to OnNavigated just has "about:blank" stored in its WebNavigateEventArgs url value.
Does anyone know what might be going on here, and/or have a way that I can fix it? I need a way to get the results from my call to the get form as I do in the other 2 platforms, rather than "about:blank". Ideally, I'd also like to get the OnNavigated call, but the important thing is the data.
Thanks for your assistance
For html form submitting, you need add the action url that used to received parameter. For example:
<form id="Myform" action="HomePage.html">
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
<input type="submit" value="Submit">
</form>
When you invoke submit, the firstname lastname field will be sended to HomePage.html page. I create HomePage that Build Action is Content in native uwp project.
Please note you could not create html in forms project. Otherwise the webview could get navigate to the right url.
This is code sample please check.

How can update an <input/> field in tapestry by AJAX request

I have a project developed with tapestry 5.
I need to update a input field (which is inside a form) using an AJAX request.
Page.tml is something like this:
<form>
<t:zone t:id="myZone">
<input type="text" t:type="TextField" t:value="product.code"/>
</t:zone>
<t:actionlink t:id="generateCode" zone="myZone">Generate</t:actionlink>
</form>
And Page.java
Object onActionFromGenerateCode() {
return myZone.body();
}
When click in "Generate" link, tapestry throws an exception. Don't let me update a zone inside a form:
java.lang.RuntimeException
The component must be enclosed by a Form component.
How can I update this input field?
thanks
Changing pieces of a form via ajax gets tricky as a FormSupport instance must be available on the Environment in the serverside event.
It might be easier to either:
Put the entire form in a zone and refresh the whole form
Execute some javascript from the serverside event
Here's how option 2 could work:
TML
<form>
<input id="productCode" type="text" t:type="TextField" t:value="product.code" />
<!-- note that async is a recent addition to eventlink in tapestry 5.4 -->
<!-- Use a dummy zone for previous versions -->
<t:eventlink event="generateCode" async="true">Generate</t:eventlink>
</form>
Java
#Inject JavaScriptSupport jss
void onGenerateCode() {
String productCode = generateProductCode();
jss.addScript("$('#productCode').val('%s');", productCode); // assuming jquery
}
Note, it is possible to dynamically change a form via ajax, it's just tricky as I said. Examples include AjaxFormLoop and the FormInjector

Internationalized Labels for Form Components in Wicket

How do I correctly create internationalized labels for my form components so that when displaying feedback messages an internationalized field name is displayed instead of the name of the field in the java code?
I've read this:
https://cwiki.apache.org/WICKET/everything-about-wicket-internationalization.html
as well as the documentation for wicket's xhtml tags:
https://cwiki.apache.org/WICKET/wickets-xhtml-tags.html
<label wicket:for="name">
<wicket:label>
<wicket:message key="label.name"/>
</wicket:label>
</label>
<input wicket:id="name" type="text" wicket:message="placeholder:label.name" />
This results in the following error:
Last cause: Expected close tag for '<wicket:label>' Possible attempt to embed
component(s) '<wicket:message key="label.name"/>' in the body of this
component which discards its body
If I replace the wicket:message with some arbitrary text it displays the text in any associated feedback messages.
(There's a related jira issue: https://issues.apache.org/jira/browse/WICKET-3903 however I still do not understand what has been done to fix this and what I must do ...)
Just found out there is a way to do this in java:
add(new TextField<String>("name").setRequired(true).setLabel(new Model<String>(getString("label.name"))));
Is it possible to somehow do this in a more comfortable way?
I just tested the following:
<form wicket:id="form">
<label for="input"><wicket:message key="input">some input</wicket:message></label>
<input wicket:id="input" type="text" name="input">
<input type="submit" value="submit">
</form>
And in the java class:
Form<HomePage> form = new Form<HomePage>("form"
, new CompoundPropertyModel<HomePage>(this));
wmc.add(form);
TextField textField = new TextField("input");
textField.setRequired(true);
form.add(textField);
In the property file I provided:
input=SomeInputField
This led to the following screen (if I leave the requiered field empty and press submit.
Is this what you are looking for?
Here is an alternative approach to #bert's that has always worked for me (wasn't aware of <wicket:label>)
The text shown for a FormComponent when a validation error occurs can be specified by means of FormComponent.setLabel(IModel). The shown text will be the result of the IModel's getObject().
TextField comp = new TextField("comp");
// Use internationalized text from XML resource file
comp.setLabel(new StringResourceModel("formResources.comp.label", this, null));
Notice this has nothing to do with <label> nor FormComponentLabel. FormComponentLabel is a component that can be used to model <label> tags.
You could even subclass FormComponentLabel to provide the label text based on FormComponent.getLabel(), and maybe output an extra mark when the field is required:
public class MyLabel extends SimpleFormComponentLabel{
private boolean required;
public MyLabel (String id, LabeledWebMarkupContainer labelProvider) {
super(id, labelProvider);
if (labelProvider instanceof FormComponent){
required = ((FormComponent)labelProvider).isRequired();
}
}
protected void onComponentTagBody(final MarkupStream markupStream,
final ComponentTag openTag) {
String mark = "";
if (required){
// could be for instance "*"
mark = getString("formResources.requiredField");
}
String text = getModelObjectAsString() + mark;
replaceComponentTagBody(markupStream, openTag, text);
}
}
{
TextField component = new TextField("component");
component.setRequired(true);
component.setOutputMarkupId(true);
IModel labelModel = new StringResourceModel("formResources.component.label",
this, null);
component.setLabel(labelModel);
add(component);
add(new MyLabel("componentLabel", component);
}
<label wicket:id="componentLabel"/>
<input type="text" wicket:id="component"/>
This way you would have clean way of
Setting the FormComponent's text to an internationalized resource string
Reusing exactly the same resource string transparently for the <label> tag and even adding custom marks to it based on FormComponent's properties.
Another alternative is to use the key attribute of <wicket:label/>, like so:
<label wicket:for="name">
<wicket:label key="label.name">Placeholder label</wicket:label>
</label>
<input wicket:id="name" type="text"/>
Unfortunately this attribute is not documented on the wiki page describing wicket's xhtml tags. All attributes supported are documented using JavaDoc in the class handling the tag (org.apache.wicket.markup.html.form.AutoLabelTextResolver).
The advantage of this alternative is that there is no additional coding required.
Wicket throws an exception to tell you that your <wicket:message> tag will be removed because the body of the <wicket:label> tag is replaced. The problem is you cannot nest the <wicket:message> tag inside the <wicket:label> tag (and shouldn't need to).
either this (Option 1):
<label wicket:for="name">
<wicket:label key="label.name"/>
</label>
<input wicket:id="name" type="text />
or this (Option 2):
<label wicket:for="name">
<wicket:message key="label.name"/>
</label>
<input wicket:id="name" type="text />
should work for you and result in HTML something like the following (assuming the properties file contains label.name=Name):
<label for="someMarkupId">
Name
</label>
<input id="someMarkupId" type="text" />
The difference is that if you set the label for the component through the Java code like so:
component.setLabel(new Model("value set in code"));
then using the Option 1 will result in the label being set to "value set in code", while using Option 2 will still result in the label set to "Name". Also if the label is set through Java code, and the key is missing from the properties file the Option 2 will throw an exception, while Option 1 will simply use the value set in the code.
I prefer this:
<label wicket:for="name"><wicket:label />:</label>
<input type="text" wicket:id="name"></input>
Just make sure to set the label in the FormComponent using setLabel, so the only java needed is:
add(new TextField("name", nameModel).setLabel(Model.of("i18n.name")));
This will be rendered as (in Dutch):
<label id="name63-w-lbl" for="name63">Naam:</label>
<input type="text" value="" name="name" id="name63">

ASP.Net MVC3 Parent Child Model Binding

I have a partial template that uses a User object as a model. The user has a collection of Accounts. On this partial template I have a loop as follows. The _Account partial template is bound to the Account class
#foreach (var item in Model.Accounts)
{
<tr>
<td colspan="6">
<div>
#Html.Partial("_Account", item)
</div>
</td>
</tr>
}
In my controller method I initially tried
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UserDetails(User user, string actionType)
But the User.Accounts collection is empty. Then I tried this. Still the Accounts collection is empty.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UserDetails(User user,
[Bind(Prefix="User.Accounts")]
FixupCollection<Account> Accounts,
string actionType)
Can I use the default Modelbinder implementation to achieve this or do I need to do anything different?
Yep, you can use the default model binder. You just need to name your fields correctly. So you need your loop to output something like this:
...
<input type="text" name="user.Accounts[0].SomeTextField" />
<input type="text" name="user.Accounts[0].SomeOtherTextField" />
...
<input type="text" name="user.Accounts[1].SomeTextField" />
<input type="text" name="user.Accounts[1].SomeOtherTextField" />
...
If you need to add/remove accounts, the hardcoded indexes get a little trickier. You could re-assign the names using javascript before postback. But it's all possible. This question gives more detail on model binding:
ASP.NET MVC: Binding a Complex Type to a Select
Use Editor Templates instead of a partial view - no need to hard code your indexes as the template will automagically index all your objects correctly, even when you add and remove Accounts. See my answer to this question:
Pass values from multiple partial views
Small write up on Editor Templates here:
codenodes.wordpress.com - MVC3 Editor Templates

Resources