blob: c3b8e127a6bc0d50f068f355d93bcdf10989e104 [file] [log] [blame]
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
= HtmlUIForTemplates
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:markup-in-source: verbatim,quotes,macros
:jbake-status: published
:syntax: true
:description: Goals
:icons: font
:source-highlighter: pygments
:toc: left
:toc-title:
:experimental:
link:Html4Java.html[Html4Java] allows us to easily use HTML based UI in
NetBeans. This page describes how to build on that ability and enhance our
template link:API_Design.asciidoc[API]s to allow rich, yet Swing independent UI
for the template creation wizards.
== Goals
* Play well with 247926 - e.g. templates independent from data loaders
* Be able to use the wizard values in templating engines - e.g. freemarker
* Plug into NetBeans wizard API
* Be embeddable into browser based environment
[[Your_Portable_HTML5_Wizard]]
== Your Portable HTML5 Wizard
To register your HTML based wizard with your template, use link:http://bits.netbeans.org/dev/javadoc/org-netbeans-api-templates/org/netbeans/api/templates/TemplateRegistration.html[@TemplateRegistration] annotation and provide reference to your HTML page:
[source,java,subs="{markup-in-source}"]
----
public class X {
@TemplateRegistration(
page = "cz/xelfi/test/x.html",
scriptEngine = "freemarker",
displayName = "JS Wizard",
folder = "Other",
content = "x.fmk"
)
public static String jsWizard() {
return "init();";
}
}
----
the return value of the annotated method should of type String and its content should be snippet of JavaScript code to execute inside of your specified HTML page (e.g. *x.html*) to create an instance of link:KnockoutJS.html[KnockoutJS] model to drive the wizard. Here is the sample of the model:
[source,javascript,subs="{markup-in-source}"]
----
function init() {
var ok = ko.observable(false);
var msg = ko.observable('');
var current = ko.observable('Init');
var data = {
'errorCode': ko.computed(function() {
if ('Init' == current()) return 0;
if (!ok()) return 1;
if (msg()) return 0;
return 2;
}),
'steps': ko.observableArray([ 'Init', 'Info', 'Summary']),
'current': current,
'ok': ok,
'msg' : msg
}
return data;
}
----
it defines wizard composed of three panels (observable *steps*) and a verification function (registered as *errorCode*) to check if everything is OK. In addition to that it defines proprietary text value *msg* which is going to be filled by the wizard and cannot be empty.
Each page of the wizard is registered as a link:KnockoutJS.html[KnockoutJS] template named according to the name of the specified step. A dummy initial page:
[source,html,subs="{markup-in-source}"]
----
<script type="text/html" id="Init">
<h1>This is Initial Page</h1>
<p>
JavaScript will ask you few questions about your mood.
</p>
</script>
----
an interactive page with checkbox and an input field:
[source,html,subs="{markup-in-source}"]
----
<script type="text/html" id="Info">
<h1>This is Query Page</h1>
<p>
Is everything OK?
</p>
<input type="checkbox" data-bind="checked: ok"/>
<p>How do you feel?
</p>
<input type='text' data-bind="value: msg"/>
</script>
----
and a simple summary page showing the specified values:
[source,html,subs="{markup-in-source}"]
----
<script type="text/html" id="Summary">
<h1>This is Summary Page</h1>
<p>
You are feeling <span data-bind="text: msg"></span>!
</p>
</script>
----
The Next/Finish buttons can be controlled by the *errorCode* property. If it is non-zero, there is an error and these buttons are disabled. Also once can use that inside of the HTML page to display user related errors:
[source,html,subs="{markup-in-source}"]
----
<div data-bind="visible: errorCode() == 1">
<span style="color: red">Please check you are OK!</span>
</div>
<div data-bind="visible: errorCode() == 2">
<span style="color: red">Tell us how do you feel!</span>
</div>
----
The L10N of the wizard is done on the level of HTML pages. The whole page gets translated into different language with appropriate suffix _x_cs.html_ and it is then selected instead of the default one, when user runs in such locale.
When the wizard is successfully finished, all the values specified in the model are transfered to the templating engine, so they can influence the content of created files. Here is a sample _x.fmt_ content which reuses the *msg* value provided by the wizard:
[source,java,subs="{markup-in-source}"]
----
Hi,
I am Freemarker.
I feel ${wizard.msg}.
----
System of this kind is portable between existing NetBeans infrastructure (see branch link:http://hg.netbeans.org/ergonomics/shortlog/62491883f7a0[WizardFor247926] in ergonomics repository) as well as demo of embedding the same wizard into browser (see link:http://xelfi.cz/htmlwizard/[on-line demo]).
[[Your_Portable_Html4Java_Wizard]]
== Your Portable link:Html4Java.html[Html4Java] Wizard
Some people prefer JavaScript, some would rather stick with Java. There is a way to provide the same model for the HTML wizard in Java, just use NetBeans link:Html4Java.html[Html4Java] link:API.html[API]s:
[source,java,subs="{markup-in-source}"]
----
@Model(className = "Y", properties = {
@Property(name = "steps", type = String.class, array = true),
@Property(name = "current", type = String.class),
@Property(name = "ok", type = boolean.class),
@Property(name = "msg", type = String.class)
})
public class YCntrl {
@ComputedProperty static int errorCode(
String current, boolean ok, String msg
) {
if ("Init".equals(current)) return 0;
if (!ok) return 1;
if (msg == null || msg.isEmpty()) return 2;
return 0;
}
@TemplateRegistration(
page = "cz/xelfi/test/x.html",
scriptEngine = "freemarker",
displayName = "HTML/Java Wizard",
folder = "Java",
content = "x.fmk"
)
public static Y jsWizard() {
return new Y("Init", false, "",
"Init", "Info", "Summary"
);
}
}
----
The HTML page remains the same (just remove the JavaScript code) and the application logic is written in Java. Here is a picture showing how the most interactive page looks like when embedded into NetBeans:
image:HtmlWizard.png[]
The picture is identical to the one generated by pure JavaScript driven wizard. Yet one can code and test in a type-safe Java. The result still remains portable as, thanks to link:apidesign:Bck2Brwsr.html[Bck2Brwsr] and other virtual machines like link:apidesign:TeaVM.html[TeaVM], we are capable to run such code in a browser as well.
[[Inception_Review]]
=== Inception Review
The issue is tracked as 248418 and inception review happened on Dec 1, 2014. The following TCRs and TCAs were raised and fixed:
* Avoid knockout templates - uses custom ko binding: link:http://hg.netbeans.org/ergonomics/rev/c5ec0030bd76[http://hg.netbeans.org/ergonomics/rev/c5ec0030bd76]
* Filter control data - done as link:http://hg.netbeans.org/ergonomics/rev/31f42048137a[http://hg.netbeans.org/ergonomics/rev/31f42048137a]
* Support for progress bar - this has evolved into supporting validation - done as link:http://hg.netbeans.org/ergonomics/rev/3c0135fb4681[http://hg.netbeans.org/ergonomics/rev/3c0135fb4681]
* Do not depend on JavaFX - done link:https://hg.netbeans.org/ergonomics/rev/6576fe363d45[https://hg.netbeans.org/ergonomics/rev/6576fe363d45]
* Prepare Technology Compatibility Kit - done link:http://hg.netbeans.org/ergonomics/rev/c2fce646315b[http://hg.netbeans.org/ergonomics/rev/c2fce646315b]
[[Final_Review]]
=== Final Review
We went through all the previous requirements on Dec 18, 2014 and found their implementation sufficient from an architecture perspective. In addition to that we also got a showcase of apisupport wizard to generate the new wizard: link:http://hg.netbeans.org/ergonomics/rev/c46aa831443d[http://hg.netbeans.org/ergonomics/rev/c46aa831443d]
The whole project seem to be ready for use by NetBeans platform users and was approved for integration, given following is done:
* arch.xml is enhanced with usecases which are currently in the wiki
* keep in mind the 'global initialization' issue.
Early adopters (like the JBossForge guys) may start testing this technology by end of 2014.
[[Global_Initialization_Issue]]
==== Global Initialization Issue
Currently the JavaScript version of the wizard initializes itself in the HTML page. While this is OK for NetBeans, it may not be acceptable for other (browser with requirejs) environments. Such global initialization might cause name clashes and we need a way to avoid them.
It has been demonstrated that one can avoid it by returning the whole JavaScript initialization code from the method annotated by @TemplateRegistration. So solution exists.
Of course it is not suitable for browser like environment as they may not have the Java method at all. But we will only see once we prototype such browser solutions. Then we will update the "wizard generating the HTML/JS wizard" to layout files more properly so sharing between different environments gets even smoother.
[NOTE]
====
The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.
This page was exported from link:http://wiki.netbeans.org/HtmlUIForTemplates[http://wiki.netbeans.org/HtmlUIForTemplates] ,
that was last modified by NetBeans user Jtulach
on 2014-12-22T10:15:41Z.
This document was automatically converted to the AsciiDoc format on 2020-03-12, and needs to be reviewed.
====