I have multiple entry points in the same module.
For example I have an Home entry point for the home page and an Admin
entry point for the admin page.
<entry-point class='com.company.project.client.HomeModule'/>
<entry-point class='com.company.project.client.AdminModule'/>
The way I am setup now - I need to check somt like this in my
OnModuleLoad:
if((RootPanel.get("someHomeWidget")!=null)&&
(RootPanel.get("someOtherHomeWidget")!=null))
{
// do the stuff
}
in order the the Admin Entrypoint not to be executed when the Home
page gets open and the other way around.
Not doing the check above also involves that if I have a div with the
same name in both the Home and Admin page whatever I am injecting in
it shows up twice on each of them.
This stinks 1000 miles away and is obviously wrong: what's the correct
way to do this in people experience?
Any help appreciated!
The correct way is to have a single entry point per module, that sticks the appropriate widgets in the appropriate divs:
RootPanel panel = RootPanel.get("someHomeWidget");
if (panel) panel.add(new HomeWidget());
panel = RootPanel.get("adminWidget");
if (panel) panel.add(new AdminWidget());
That way it just scans the page looking for any divs you have and inserts the appropriate widget. So your HTML page determines what widgets are displayed when and the GWT code is ready to handle any situation. There's nothing about the above that stinks, it's the way your entry point should be written.
The alternative is if your admin area and normally area are totally different (eg: you want to load them at separate times) then they should be separate modules, with separate entry points.
I also wanted to use multiple pages in a GWT toy app and I think I figured it out. It took some massaging of the deployment descriptor (myApp.gwt.xml), but here's what I did.
Made another class implementing EntryPoint and added some code that added to a div only in the new page.
Copied the original gwt.xml and changed two things:
The module-rename-to - I changed to "anothergwtapp"
The entry point specified the new class.
When I compile the project, there is another directory in the "war" folder called (wait for it...) "anothergwtapp". It contained the "anothergwtapp.nocache.js" that is the GWT magic.
Finally, I copied the orginal HTML page and replaced the "stockwatcher/stockwatcher.nocache.js" with "anothergwtapp/anothergwtapp.nocache.js" (yes, I'm very new - the tutorial is still on my machine)
I changed the new HTML to be a little different (new divs for the new entry point's onload to populate) and I added a simple href to the new page in the first page.
It worked. Just duplicate the gwt.xml and provide a new name for the module to go along with the new app page. I looked at some of the other links and I may have actually done what was described, but there were too many words and redirects and such (i.e. I didn't really read anything). I am using the latest GWT plugin for Galileo so maybe IJWs now.
Dont consider Admin and home page as different pages. Concept of pages is not applicable to GWT, as there is only one single page, ie single entrypoint.
If you want to give effect of different pages, then use URL rewriting features of GWT.
If you do want to use different Entrypoints, then as said in above comment, use different modules.
It's usually better to only have one EntryPoint. Multiple EntryPoints in one module all start at the same time and that can sometimes do things you did not expect.
You have plenty of options in how to handle it separately:
- Have 2 different compilations one for Admin and one for the Home application.
- Use the history tokens to indicate that you want Admin or Home
- Check a JS variable to show one or the other
- Check the presence of a specific DIV id to show Admin or Home (RootPanel.get(id))
- Use URL parameters to indicate the application.
- ... etc
There is a simple (tricky) way to achieve this:
Make a Main class Your entry point.
<module rename-to='gwt'>
<inherits name='com.google.gwt.user.User'/>
<entry-point class='com.example.client.Main'/>
<source path='client'/>
<source path='shared'/>
</module>;<br/>
Create this Main.java to work like a dispatcher:
package com.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
public class Main implements EntryPoint {
public void onModuleLoad() {
String url = Window.Location.getHref();
if ( url.indexOf("?install")>-1 ) {
Install install = Install.getInstance();
RootPanel.get().add(install);
else if ( url.indexOf("?admin")>-1 ) {
Admin admin = Admin.getInstance();
RootPanel.get().add(admin);
} else {
Application app = Application.getInstance();
RootPanel.get().add(app);
}
}
}
Now the different classes Application, Admin and Install
work like seperate units.
Here is for example a simple Install:
package comexample.client;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
public class Install extends FlowPanel {
/** Singleton stuff - to access Main from all subclasses! */
private static Install singelton;
public static Install getInstance() {
if (singelton == null) {singelton = new Install();}
return singelton;
}
/** Constructor - called by Main.onModuleLoad() */
private Install() {
this.add(new HTML("<h1>Do whatever You have to do!</h1>"));
}
}
You don't need the Singleton stuff (getInstance), but it is very handy in big applications.
Now in the /war-directory create directories named install and admin and in very of them create an HTML page like this:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; URL=/index.html?install">
</head>
<body></body>
</html>
So when the user directs his Brower to http://www.example.com/install he will be redirected to http://www.example.com/index?install and index.html is bound to Main.java which will dispatch the request and load Install.java
Related
l split my GWT code in different different modules like
PrintPermit.gwt.xml
EmployeeResponse.gwt.xml
Rejected.gwt.xml
and every module has its own entry point class
in my HTML host page I am calling script like
ae.init.EmployeeResponse.nocache.js
I have a menu like
Print Application
Reject Application
New application
whenever user will click on new application default new application will open
as I declare EmployeeResponse.nocache.js statically in my HTML host page.
now I want to call other modules on click button print and reject button
how can i call nocache js for print and reject modules. is there any way to dynamic call.
please help me guys.
Here's how I've done it in the past:
First of all, in the module you want to export, you need to make sure that the code you're going to export doesn't end up obfuscated. This can be accomplished with the liberal use of #JsType; this is the new way of exporting JS, available in GWT 2.8 (as opposed to JSNI).
Your module's entry point onModuleLoad can be empty; it doesn't need to do anything.
Include your JS in the HTML you want to use (maybe the same page as your "main" module)
Check JSInterop documentation (perhaps the one available here) on how you can use native JS in your GWT app (because now, your GWT module became native JS). Import the classes via JSInterop from your library, and use them.
Please be aware of the async nature of the GWT JS loading; your library will be loading in an async manner, just like any JS application (and therefore, it won't be available immediately when your page loads). To overcome this, I've placed a call to a native JS function in my library's onModuleLoad function (i.e. to make sure you notify any potential listeners that the code has loaded; because when onModuleLoad runs, the code surely loaded).
There is a example of an InterAppEventBus:
https://github.com/sambathl/interapp-eventbus
which shows the communication between two GWT applications.
I have adopted it and replaced JSNI with Elemental2 and WebStorage:
https://github.com/FrankHossfeld/InterAppEventBus
Hope that helps.
You can achieve this through separate Html file for each module.
So first of all create separate html for each application e.g. PrintPermit.html and specify corresponding nocache.js in each html.
then on your buttons in menu, add click handlers and in each on click load a corresponding html through Window.open()
e.g. for PrintPermit,
printPermitButton.addClickHandler(new ClickHandler{
#Override
public void onClick(ClickEvent arg0) {
String s = GWT.getHostPageBaseURL() + "PrintPermit.html";
Window.open(s, "PrintPermit", "");
}
});
Please note the window.open will open in new tab in browser, you can also use gwt iframe to open html in same browser page.
Each module will have corresponding nocache.js and will be loaded through html using Window.open()
Im using the login example from the Meteor React Tutorial
meteor add accounts-ui accounts-password
Its all ok but Im trying to find the file and change it but I dont know where is it.
This is my code:
import { Blaze } from 'meteor/blaze';
export default class AccountsUIWrapper extends Component {
componentDidMount(){
this.view = Blaze.render(Template.loginButtons,
ReactDOM.findDOMNode(this.refs.container));
}
componentWillUnmount(){
Blaze.remove(this.view);
}
render(){
return <span ref="container"/>
}
}
And i have installed meteor add useraccounts:materialize
How can I put the template on this?
You need to put your component inside /imports/ui/ directory and name the file as AccountsUIWrapper.jsx
So it will be saved as /imports/ui/AccountsUIWrapper.jsx.
Then you can import your wrapped component inside /imports/ui/App.jsx file with:
import AccountsUIWrapper from './AccountsUIWrapper.jsx';
And then use it in your React render function in the same file as:
<AccountsUIWrapper />
The tutorial lays it out pretty clearly, including all the filenames and locations. You should be able to access their GitHub repository for the same.
If you want, for reference, you can also take a look at my code at this particular step back when when I did this tutorial myself.
Update: For useraccounts:materialize
The useraccounts:materialize package that you have mentioned depends on useraccounts:core package as its base. So you cannot apply useraccounts:materialize to default meteor accounts package directly.
Follow the instructions on useraccounts:core to set it up. You may need to remove accounts-ui as well, as it would likely clash with the above packages.
Then, go through the documentation for useraccounts that shows how to render their accounts template in Blaze.
After that, using the same way as shown in the tutorial, you should be able to create a new React wrapper for useraccounts:materialize Blaze template.
Here are links to boilerplate useraccounts:materialize code for Iron Router and Flow Router. From these you can take reference for the Blaze template code, which you can then wrap in React:
Boilerplate with iron:router
Boilerplate with FlowRouter
I am brand new to NancyFX and currently enthralled by its low-ceremony approach to web application development. Throwing myself in at the deep-end, I also want to use CoffeeScript and investigate the benefits of Sass.
The Set-Up
To enable this combination I have created a new Empty Web Application using the VS2010 template (found in the Nancy Accessories project). I have then used the VS PackageManager to Nancify my application and add the SassAndCoffee support:
PM> Install-Package Nancy
PM> Install-Package Nancy.SassAndCoffee
So far so good. I then created an ~/Content/scripts folder and in there I have placed a file called home.coffee containing the following line of CoffeeScript.
alert "Hello Nancy!"
Now things start to get a bit fuzzy. I want to run this script on the client so I create an view called ~/Views/home.sshtml (and associated NancyModule with Get["/"] route - not shown). The view's html looks like this:
<head>
<title>Hello Nancy</title>
<script type="text/javascript" src="/content/scripts/home.js"></script>
</head>
<body>
<p>Hello #Model.User</p>
</body>
</html>
The view works just fine but the link to the home.js file just returns a 404: Not Found.
I am hoping that somehow Nancy will magically work out that I need my CoffeeScript compiled to JavaScript when it looks for the referenced home.js file and finds the home.coffee instead. This didn't work - so much for inspired guesswork.
If I change the script tag above to point to the existing home.coffee instead then the file is found but processed as a normal JavaScript file giving errors concerning the lack of tiresome ceremony namely: "unexpected string"
The Question
Now you know my set-up and simple requirements, here then is my question:
How do I get CoffeeScript to 'just work' using the NancyFX framework?
Thank you
Update
Steven Robbins (below) has answered this question by pointing to the demo code. But just in case you don't want to pull MBs of source from GitHub, here are the lines required to get things going. First add a class called Bootstrapper.cs to your project. Now add the following code (it worked like a charm for me):
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
StaticConfiguration.DisableErrorTraces = false;
Hooks.Enable(pipelines, new InMemoryCache(), container.Resolve<IRootPathProvider>());
}
}
The SassAndCoffee project doesn't hook into the static content bit in Nancy, it (or something similar) may in the future, but at the moment it's just a separate pipeline hook.
If you take a look at the sample project on github:
https://github.com/NancyFx/Nancy.SassAndCoffee/tree/master/src/Nancy.SassAndCoffee.Demo
That should show you how to get it going.
On my gwt project. i have a script that call the dictionary:
<script type="text/javascript" src=conf/iw_dictionary.js></script>
instead of writing this script element in the html file. i want to inject it into the html from the entry point, on the module load.
how can i do it?
Use com.google.gwt.core.client.ScriptInjector, since it was created specifically for stuff like this
ScriptInjector.fromUrl("conf/iw_dictionary.js").setCallback(
new Callback<Void, Exception>() {
public void onFailure(Exception reason) {
Window.alert("Script load failed.");
}
public void onSuccess(Void result) {
Window.alert("Script load success.");
}
}).inject();
Basically you inject the script element in your onModuleLoad():
Element head = Document.get().getElementsByTagName("head").getItem(0);
ScriptElement sce = Document.get().createScriptElement();
sce.setType("text/javascript");
sce.setSrc("conf/iw_dictionary.js");
head.appendChild(sce);
The browser will automatically load it as soon as it's injected.
You could simply add a <script> element in your *.gwt.xml file.
<script src='conf/iw_dictionary.js' />
onModuleLoad will only be called once the script is loaded (as if you had it in your html page).
The answers form jusio, Dom and Thomas Broyer are all valid here. In my particular case, I was looking to inject a series of polyfill scripts into GWT for some IE8 support we needed when running native JS code. The polyfill scripts needed to be available to the GWT iframe's window context - NOT the host page. To do that, using ScriptInjector was the correct approach as it attaches the script at that level. You can make ScriptInjector install the scripts to a host window by using setWindow(TOP_WINDOW). Adding scripts with the <script> tag in my *.gwt.xml file seemed to be attaching to the host window as did using #Dom's approach.
Im new about this technology, but I would like to know if is possible to create new object (html elements, such div/span/and so on...) dinamically on server and send it to the client, or if i can just load the ones made on client-side when i develop it in the application.
I don't ask how to do it (i think its a delicate argument), but if I can, and (if yes) where i can get some stuff/example/tutorial to do this.
Example
What i usually do :
...
public void onSuccess(Boolean result) {
if(result) {
myFunction();
}
}
...
myFunction() {
InlineLabel label=new InlineLabel();
this.add(label)
}
What im looking for :
...
public void onSuccess(InlineLabel result) {
this.add(result)
}
So, i don't need to load in advance the Object, but load them only if i click on some button (or if i perform an action). This will save a lot of code (that is inutil, if i don't do any action) loaded (as JavaScript) on the client.
As usual, thanks for your time!
GWT does not support the pattern you showed, but you can achieve a similar effect with "code splitting": read http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html
With code splitting, the client only downloads the script it needs right away (configured by the developer). If, for example, the user navigates to a more complex area of the UI that requires more widgets, additional code will be downloaded.
I'm not entirely sure I understand your question, but please feel free to amend your question or post a comment if I've missed the mark.
The host page
A GWT app is loaded in the following (simplified) process:
A host page (HTML) is loaded
A bootstrapping script is loaded
A compiled app script is loaded
The host page can contain any HTML you want. The only requirement is that you include a <script> element that loads the GWT bootstrapping script.
As a result, you can have the server return a page that contains any server-generated markup you like.
Server-rendered HTML at runtime
Once your app is running, you can send off asynchronous requests in your code to retrieve arbitrary data from the server. One option is to retrieve server-generated HTML and insert it into your application.
For this option, you'll want to instantiate an HTML widget, then use its setHTML method to insert the server-generated markup into the widget.
Client-generated
As an alternative, you can retrieve structured data from the server via GWT RPC. Objects created on a Java-based server are serialised by GWT on the server and deserialised on the client back into regular objects. You can then pull data out of these objects using accessor methods (getName, getId, etc.). At this point, you have several options:
Generate some HTML using StringBuilder and the like, then use setHTML on an HTML widget.
Generate DOM elements with the DOM class
Set the data into widgets and add them to panels or the root panel.