Re: D2W/ERModernLook in non D2W app
Re: D2W/ERModernLook in non D2W app
- Subject: Re: D2W/ERModernLook in non D2W app
- From: Ramsey Gurley <email@hidden>
- Date: Thu, 10 Jun 2010 10:45:50 -0400
On Jun 10, 2010, at 10:36 AM, Ramsey Gurley wrote:
Instead of thinking of it as embedding D2W into your app, I think it
may help if you look at as embedding your app into D2W.
Let me explain that. You say you want to take your existing wrapper
and embed the D2W admin stuff into the ajax update container. The
thing is, the wrapper is a subcomponent of your Main page. You
probably know this already, but I found it really counter-intuitive
until I saw this diagram:
http://developer.apple.com/legacy/mac/library/documentation/WebObjects/Developing_With_D2W/Architecture/Architecture.html#/
/apple_ref/doc/uid/TP30001015-DontLinkChapterID_2-BAJJHJGE
Once I understood that the wrapper is the child, and not the other
way around, things started to make more sense to me.
Anyway, to load a D2W page into your page wrapper, you either have
to embed it in your existing page inside the update container or
load a D2W page in place of your Main. (I'm assuming the update
container is in your main, and not in your wrapper) If you are new
to D2W, just linking off to the D2W admin pages will be easiest.
Those admin pages can even reuse your current page wrapper to keep
the look of your main site. All you really need to do to accomplish
that is to add a wohyperlink on your page that fires an action that
returns something like
D2W.factory().defaultPage(session());
That puts you on a D2WPage and then it's turtles all the way down
(^_^)
If you want to use the modern look specifically, that framework
loads its css resources a little differently than you may expect, so
looking at how it happens in an empty modern app constructed with
the modern template should help a lot. You may need to consult the
Davids for the particulars there.
The wrapper is just an ordinary component though. If you're getting
a null pointer, it's because that wrapper component assumed it would
always be embedded in a D2W page and that is not the case for you.
So, it's just your typical debugging mission. Find where the error
is happening, and don't let the lack of a D2W context cause a crash
for your non-D2W main component. It could be as simple as
if(context().page() instanceof D2WPage) {
// D2W dependent code here
}
Note: You could just drop the page wrapper and menu header from the
template into your app and link off using
D2W.factory().defaultPage(session()); if merging the wrappers into a
single wrapper is too much headache.
Good luck and keep us posted on your progress (^_^)
Ramsey
You never needed the modern css on your Main page before, so you
shouldn't need it now.
The other way involves embedding D2W pages into your page using
D2WList, D2WInspect, D2WQuery and the like. The bindings on those
components are fairly straightforward, but it's going to be more
work and probably require a somewhat better understanding of D2W.
HTH,
Ramsey
On Jun 10, 2010, at 9:51 AM, Andrew R. Kinnie wrote:
OK, I just redid everything, and got back to exactly the same
error. I have essentially no idea at all what to even look at at
this point.
Andrew
On Jun 9, 2010, at 7:07 PM, David Holt wrote:
Hi Andrew,
On 9-Jun-10, at 3:34 PM, akinnie wrote:
OK, that all makes sense.
:-)
I didn't think I needed a home() method as I was putting it in a
subcomponent, so I commented it out.
homeAction() is just a name. Don't be confused by that. In this
case, David arbitrarily made the choice that the homeAction was
the customary QueryAll page for the ERModernMoviesDemo. It might
just as easily be a list of users, or a search page for bugs, or
whatever you want. You just need to call the method from your
"Admin" tab, whatever it is called. For example you might want to
call it adminHomePage(). That just doesn't matter.
The D2W.factory().defaultPage called in the homeAction is set in
the Rules. If you open up the rules for JavaDirectToWeb framework
you'll find
0 *true* startupTask = "queryAll"
This is what is being used by defaultPage to render the QueryAll
page component.
If you prefer a different task to be your beginning task, set your
new 'startupTask' at a higher priority in the rules and make sure
that you specify a 'startupEntityName' as well (any task other
than queryAll acts on an entity).
The Factory class in BugTracker gives you all sorts of options for
actions that you could call from your navigation scheme (for
example you could display a qualified list of entities based on
your logged in user). This is where ERXThreadStorage comes in
handy because it is accessible from your EOs.
I think. I am in school at the moment, so I do have it in front
of me. Hopefully, if I'm not a zombie, I'll be able to look at
it after 10:30 tonight.
Thanks to you and Ramsey for all your help. . . not to suggest I
won't need more tomorrow.
Not a problem. It is my hope that I can be of some help!
David
Andrew
On Jun 09, 2010, at 05:27 PM, David Holt <email@hidden>
wrote:
Hi Andrew,
On 9-Jun-10, at 1:12 PM, Andrew R. Kinnie wrote:
yeah, I just noticed that. I was still doing it the old
(Ajaxy) way. I also noticed that I didn't replicate the
MenuHeader (and instead just included an ERXNavigationMenu
directly in Admin), so I changed that, and then I got a session
timed out error.
I don't think you need the menu header unless you want the extra
navigation buttons at the top of your header.
I have an admin() method in my Main component (which I use as a
wrapper . . . in the non d2w sense, i.e. it's not bound to that
key in the rule, it's for general site visitors). All it did
was check which component was loaded as currentPage, and load
that into the wrapper's content area. Obviously not
appropriate in this case. I changed it to just return a
WOActionResults which is an instance of Admin.
That has the same result as before. NPE because the context is
null.
ERD2WHead.java 32 displayNameForPageConfiguration
er.directtoweb.components
How should I do this?
You need to use the D2W Factory to create your admin page. So
you first decide what kind of page it is (list of all entities?)
and then use the interface to create it.
So if you take a peek in MoviesNavigationController you'll see a
bunch of actions such as:
// MOVIES
public WOComponent queryMovieAction() {
return queryPageForEntityName(MOVIE);
}
public WOComponent createMovieAction() {
return newObjectForEntityName(MOVIE);
}
Which then call:
// GENERIC ACTIONS
public WOComponent queryPageForEntityName(String entityName) {
QueryPageInterface newQueryPage =
D2W.factory().queryPageForEntityNamed(entityName, session());
return (WOComponent) newQueryPage;
}
public WOComponent newObjectForEntityName(String
entityName) {
WOComponent nextPage = null;
try {
EditPageInterface epi =
D2W.factory().editPageForNewObjectWithEntityNamed(entityName,
session());
epi.setNextPage(session().context().page());
nextPage = (WOComponent) epi;
} catch (IllegalArgumentException e) {
ErrorPageInterface epf =
D2W.factory().errorPage(session());
epf.setMessage(e.toString());
epf.setNextPage(session().context().page());
nextPage = (WOComponent) epf;
}
return nextPage;
}
If you just want to try out your Admin page, try the
homeAction() from the controller. It should work out of the box
to create your QueryAll page. If it doesn't work, then we'll
know you've done something wrong with your setup. All the
navigation actions called in the ERModernMoviesDemo
NavigationMenu.plist are routed through this controller. If you
want a much more detailed look at things that are possible,
check out the Factory class in the BugTracker application.
// NAV ACTIONS
public WOComponent homeAction() {
return D2W.factory().defaultPage(session());
}
David
On Jun 9, 2010, at 4:00 PM, David Holt wrote:
How are you calling the Admin page?
David
On 9-Jun-10, at 12:49 PM, Andrew R. Kinnie wrote:
Sorry, didn't reply all with my last reply.
Begin forwarded message:
Thanks David and Ramsey. I seem to be having issues,
unfortunately.
To clarify, originally, I was planning to have the admin
component be a subcomponent within the normal wrapper (by
"normal I mean pre-d2w -- not "non"-d2w as I previously
suggested. I meant the site works without d2w, I just
thought adding the admin as d2w would be a good way to learn
d2w). Anyway, I attempted to accomplish this by making my
Admin component essentially a copy of the PageWrapper from
ERModernMoviesDemo . . . but got confused by the head and
body stuff. Now I see that was likely the source of many of
my issues.
So now I am trying to do exactly what you suggest and open
a new window with a page level admin component via D2W.
(restoring the html, head and body tags). Now, however,
when ERD2WHead asks for this:
D2WContext context = (D2WContext)
context().page().valueForKey("d2wContext");
I am getting null. I have the d2wContext method inside my
Admin component (copied from the modern movies demo), and
also have the body class method.
public D2WContext d2wContext() {
if (context().page() instanceof D2WPage) {
D2WPage d2wPage = (D2WPage) context().page();
return d2wPage.d2wContext();
}
return null;
}
public String bodyClass() {
String result = null;
String pageConfig =
(String)d2wContext().valueForKey("pageConfiguration");
if (pageConfig != null && pageConfig.length() > 0) {
result = pageConfig + "Body";
}
return result;
}
HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//
EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<webobject name = "HeadTag">
<webobject name = "StyleSheets" />
</webobject>
<webobject name = "BodyTag">
<webobject name = "IsDebug">
<div id="ERD2WDebugFlags"><webobject name =
"ERD2WDebugFlags" /></div>
</webobject>
<div id = "ContentWrapper">
<div id = "MenuHeader">
<webobject name = "ERXNavigationMenu"/>
</div>
<div id = "MainContent"> <webobject name =
"MainContent" />
</div>
</div>
<webobject name = "WOLToolBar"/>
<webobject name = "ERMD2WStyleSheetInjector"/>
</webobject>
</html>
wod:
ERXNavigationMenu : ERXNavigationMenu {
navigationContext = navigationContext;
}
MainContent : WOComponentContent {
_unroll = YES;
}
BodyTag : WOBody {
class = bodyClass;
}
HeadTag : ERD2WHead {
}
EntitiesMenu : MenuHeader {
}
ERD2WDebugFlags : ERD2WDebugFlags {
context = d2wContext;
}
IsDebug : WOConditional {
condition = application.isDevelopmentMode;
}
StyleSheets : ERMD2WCSSReference {
localContext = d2wContext;
}
WOLToolBar : WOLToolBar {
expanded = true;
}
ERMD2WStyleSheetInjector : ERMD2WStyleSheetInjector {
localContext = d2wContext;
}
I still have the rule in my rule file telling the
pageWrapperName to be "Admin"
Still isn't loading. I assume there is something else I am
missing. (Note I am for now, abandoning doing the
subcomponent method.)
On Jun 9, 2010, at 3:32 PM, David Holt wrote:
Hi Andrew,
In order to minimize the work that you need to do, I would
consider rethinking your approach to the admin side.
Instead of it opening inside your AUC, why don't you have
the admin link open up a nice full page completely outside
your current pagewrapper with the unchanged ERModernLook
all ready to go?
Your admin link will call something like
session.navController.adminAction() (see the
ModernMoviesDemo for examples), and you will include the
PageWrapper and MenuHeader from the example in your
application. Then the D2W rule system will find the
pagewrapper, menuheader and skin framework required to make
the complete page. Part of your navigation strategy on the
Admin/D2W side will need to include a link back to reload
the "normal" page wrapper.
Once you figure out how D2W ties all this together, it will
be easier to figure out how to frame it within your
original strategy.
If you want to go ahead with your current strategy see
further notes below...
Also see David LeBer's responses in the thread from a few
weeks ago which will give you some idea of the complexity
involved in the opposite problem: "embedding standard
components into ERModernDirectToWeb"
On 9-Jun-10, at 11:10 AM, Andrew R. Kinnie wrote:
Thanks. I added a rule in the d2wmodel file for
pageWrapperName. However, I managed to discover several
other problems.
The pagewrapper will need to include a call to the D2W
context. Every ERModernLook page needs access to this.
My page wrapper was for a non-d2w page and site,
<aside>This is a common misconception. There's really no
such thing as a non-D2W site. You can use as much or as
little D2W as you wish. Your pages are either created by
the D2W factory or they're not. Your web application either
includes the D2W frameworks or it doesn't. Those are the
distinctions, rather than "D2W App" or "non-D2W app".</aside>
and I want the d2w stuff to be a subcomponent of this. It
is very simple, I have a header, sidebar navigation, and
an AjaxUpdateContainer which changes based on what link
the user clicks on the navigation sidebar. One of these
links is the Admin link, which will (I hope) cause the D2W
stuff to be loaded into the AjaxUpdateContainer, without
disturbing anything else.
Your PageWrapper component will need to provide the
D2WContext. If you plan to go with ERModernLook you're
going to have to look carefully at the CSS. I am pretty
sure that it also depends on the body class being in your
PageWrapper.
I therefore made my Admin component into the
"pageWrapperName" for the purposes of the D2W rule, and
created it based on the pageWrapper from ERModernMoviesDemo.
Not sure what you mean here. Is the Admin component
included inside the AUC or is it going to be a page level
component?
1. I changed it to remove the header because this is a
subcomponent. However, this removed the stylesheets tag.
I also eliminated the bodyTag webobject, again, as this is
a subcomponent. Neither of these seem to affect this
problem though.
I think that D2W expects whatever component you use for the
PageWrapper to contain the page level HTML. All the D2W
page level components would depend on that. Otherwise what
you might be looking for are the embeddable components
(remember that there was a palette of these things in
WOBuilder?).
This works, sort of, but the WOLToolbar appears as a ul
above the ul of the entities. (I had an error here until
I added the WOLips framework and password) I assume this
is related to the navigation panel not being styled
properly.
Yeah you're messing with the assumptions that were made in
creating the CSS for ModernLook, I expect. The WOLToolbar
is styled to be at the bottom of the page.
The real problem is that when I click an entity, now I get
an NPE error:
ERMD2WStyleSheetInjector.java 39 resourceFrameworkName
er.modern.directtoweb.components
Which apparently means it's not getting the skin framework
(and also isn't supplying the default of "app") I added
the property to the skin framework's properties file (then
added it to the app's properties too to see if that
changed anything. It didn't. I assume this is related to
the missing stylesheets from the head.
This is established by the rules. You've messed with the
framework's assumptions for the styling.
2. I then added the head and body back (along with the
bodyClass method lifted from the ERModernMoviesDemo's
pageWrapper). I changed it from an Ajax link to a regular
WOHyperlink and set target = "new" but now I get an NPE
like this (before I get to the uls from the WOLToolbar or
the entitities) :
ERD2WHead.java 32 displayNameForPageConfiguration
er.directtoweb.components
(Note this also happens inside the AjaxUpdateContainer if
I keep it as an AjaxUpdateLink with the appropriate
containerid)
You can't use the head and body tag nested inside a
component that contains head and body tags (which I am
assuming your Main component does)
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden