it's very difficult to find a complete step-by-step guidelines of How to properly use CSS in GWTP on internet.
I am using eclipse & GWTP to build my app & I want to set some simple Css styles for my widgets (button, textbox...).
Ok, here is what I got: a TestPresenter.java, TestView.java & TestView.ui.xml
-In TestView.ui.xml:
<ui:UiBinder .....>
<ui:style src='myStyle.css' />
<g:HTMLPanel>
<g:Button text="My But 1" addStyleNames="{style.myBut}" ui:field="myBut1"/>
<g:Button text="My But 2" ui:field="myBut2"/>
</g:HTMLPanel>
</ui:UiBinder>
myStyle.css is in the same folder that houses TestPresenter.java, TestView.java & TestView.ui.xml
-TestPresenter.java (has 2 buttons- myBut 1 & myBut 2): I added "myBut" for myBut2
getView().getMyBut2().addStyleName("myBut");
After running, it shows 2 buttons, the first myBut1 got the correct CSS but myBut2 still show the default Css. I changed to getView().getMyBut2().setStyleName("myBut"); but it still didn't work.
So i think probably i'm missing some classes here & that is why eClipse couldn't recognize "myBut" CSS so that it can apply for myBut2.
So, How to let myBut2 show the correct Css in eClipse?
the reason is that adding a CSS style sheet as a source to the uibinder causes the gwt compiler to generate a CssResource class for it, and therefore obfuscating the CSS class name to SHA1 hash.
That mean that in the final compiled version, instead of ".myBut" you actually end up with something like ".XYZXYZ".
this is purely GWT uibinder behavior that you can read about here
Specifically for GWTP, the textbook solution is:
in TestView.java add:
public TestView extends SomeGWTPViewClass implements TestPresenter.MyView
{
public interface MyStyle extends CssResource
{
String myBut();
}
#UiField MyStyle style;
#Override
MyStyle getStyle()
{
return style;
}
//rest of code here......
.....
...
}
in TestView.ui.xml change ui:style to:
<ui:style src='myStyle.css' type="fully.qualified.package.name.TestView.MyStyle"/>
in TestPresenter.MyView interface add:
MyStyle getStyle();
now you can access the myBut style in TestPresenter by:
getView().getMyBut2().addStyleName(getView().getStyle().myBut());
Related
I am using Angular, my goal is to be able to use a string declared in typescript inside a CSS file. I am trying to set the background image of a navbar component. Later on, the background image path will be received from a database service, that's why I need it to be in the typescript file. I read something about using [ngStyle], but the img will not be updated, I just need the paths to be received from a database. Should I still try to use it? And how? I am a bit lost.
My typescript file has something like:
// ...
export class NavbarComponent{
background_url='../../../assets/img/background.png';
constructor() { }
// ...
And in my CSS file i want to do something like:
nav{
background-image: background_url;
}
However, this isn't working for me.
How could I better approach this? Thanks
I think it's not possible to access the ts file variables from the CSS file, but you can get elements from DOM and set style to that from the ts file.
an example:
document.getElementById('element').style.backgroundImage = background_url;
also if you are using frameworks like angular, you can use #ViewChild to get elements from DOM and style them by using the renderer2 library like this:
export class NavbarComponent {
#ViewChild('element') element: ElementRef;
background_url='../../../assets/img/background.png';
constructor(private renderer: Renderer2) {}
setStyle() {
this.renderer.setStyle(
this.element.nativeElement,
'background-image',
this.background_url
);
}
}
and then call the setStyle function where ever you want.
more from renderer2: https://angular.io/api/core/Renderer2
Since my application got larger, I decided that each "module" of my application, will have its own resource file, style file and GSS file. Also styling of for example buttons will be in a different, global GSS file as it is more of an application style, used through the application.
This is not a problem, but when I wanted to do something like this:
.buttonGroup>.button.active{ background-color: red}
in one of the modules, it does not match anything.
Since the button style(buttonGroup, button, active) and behavior (add "active" class on click) is specified in different (global) GSS file, I am not able to change the style of the "active" class.
Here is a simplified example:
public interface AppResources extends ClientBundle {
public static AppResources INSTANCE = GWT.create(AppResources.class);
#Source({"style.gss"})
AppStyle appStyle();
}
Style file:
public interface AppStyle extends CssResource {
String buttonGroup();
String button();
String active();
}
Module:
public interface ModuleResources extends AppResources{
public static ModuleResources INSTANCE = GWT.create(ModuleResources.class);
#Source({"style.gss","module.gss"})
ModuleStyle moduleStyle();
}
Style file:
public interface ModuleStyle extends AppStyle {
}
In GSS files I tried to use #provide and #require (it would not compile without it as it would have missing identifiers or classes).
It then compiles fine, but the buttonGroup, button and even the active class is treated as it belongs to the AppStyle, therefore style.gss styles are used and the rule:
.buttonGroup>.button.active{ background-color: red}
in module.gss is not matching anything as it is probably looking for .hash-ModuleStyle-buttonGroup, .hash-ModuleStyle-button and .hash-ModuleStyle-active classes, whereas the actual styles on the button are .hash-AppStyle-buttonGroup etc.
In the end I solved it by using #external on the classes I wanted to use in different GSS stylesheets.
By using #external all the classes from widgets, which had their own stylesheets, keep their class names unobfuscated, so that they can be overridden in any module stylesheet.
I didn't want to do it before, but that was the only solution that I could think off.
This is actually exactly what #Import is meant to solve!
Using GWT 2.1, I am trying to create a CSS file that contains numerous constants and common styles. I would like to use the ui:style tag to include it in the UiBinder template:
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
<ui:style field="css" src="constants.css" />
</ui:UiBinder>
I can easily utilize the styles for elements:
<g:FlowPanel styleName="{css.panel}">...</g:FlowPanel>
But attempting to use the constants in another Style block fails:
<ui:Style>
.templateSpecificStyle {
background-color: {css.royalBlue};
padding: 1em;
}
</ui:Style>
Oddly I do not receive a compile error. The obfuscated CSS class is created; however, the content is empty. Is there any way to access these CSS constants within another Style block? Is it possible using the older ResourceBundle / CssResource pattern?
After re-reading https://stackoverflow.com/questions/3533211/need-app-wide-css-constants-in-gwt/4143017#4143017 I see that the constants work if you add the template specific style within the style block:
<ui:Style src="constants.css">
.templateSpecificStyle {
background-color: royalBlue;
padding: 1em;
}
</ui:Style>
This is perfect for my needs.
It may be in your best interest to define these constants in some class, then use runtime substitution to include this constant in each CSS resource you intend to use.
CSSConstants.java
package com.foo.client;
public final class CSSConstants {
public static final String ROYAL_BLUE = "#4169E1";
}
Style block in UiBinder template
<ui:style>
#eval royalBlue com.foo.client.ROYAL_BLUE
.templateSpecificStyle {
background-color: royalBlue
}
</ui:style>
Note that even the name of the technique is "runtime substitution", the GWT compiler will replace royalBlue with a string literal because the value of royalBlue can be evaluated at compile time.
For more cool stuff that you can do in CSS resources, take a look at http://code.google.com/webtoolkit/doc/latest/DevGuideClientBundle.html#CssResource
I have a simple UiBinder widget containing a TextArea:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:TextArea visibleLines="3" />
</ui:UiBinder>
I want to control the background color of this textarea for writeable and read only states. GWT uses the "-readonly" style name decorator to achieve this. So I try this:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
.textBoxStyle {
background-color:yellow;
}
.textBoxStyle-readonly {
background-color:lightgray;
}
</ui:style>
<g:TextArea styleName="{style.textBoxStyle}" visibleLines="3" />
</ui:UiBinder>
Obviously this won't work because style names are obfuscated for CssResources resulting in something like this:
.G1x26wpeN {
background-color:yellow
}
.G1x26wpeO {
background-color: lightgray;
}
The result HTML for writeable textarea looks like this:
<textarea tabindex="0" class="G1x26wpeN" rows="3"/>
The read only textarea looks like this:
<textarea tabindex="0" class="G1x26wpeN G1x26wpeN-readonly" readonly="" rows="3"/>
How do I declare the style so GWT will obfuscate the primary part but not the "-readonly" decdorator?
I know that I can disable the obfuscation for the entire style name. But I'd like to keep the obfuscation while making use of the decorators.
At this moment (GWT 2.4) it is not supported, and it's not clear if/when it will be supported, see issue 4746 in the GWT issue tracker.
The workaround is to add #external, which disables obfuscation for those styles. In this case that would be:
#external textBoxStyle, textBoxStyle-readonly;
If you want to use this style for all your read-only TextAreas then I'd suggest just modifying the .gwt-TextArea-readonly style in your GWT theme CSS file.
Otherwise, I can only think of adding your custom style programmatically when you set the TextArea read-only.
PS: from the docs:
<set-configuration-property name="CssResource.obfuscationPrefix" value="empty" />` can be used for minimal-length selector names, but this is only recommended when the GWT module has total control over the page.
I recommend using this (with "empty" or "X" or other unused prefix) for much shorter class names - because at default settings you don't gain that much through obfuscation (textBoxStyle - 12chars, G1x26wpeN - 9chars, X0 - 2 chars ;)).
Why don't you try sth like this
public class MyFoo extends Widget {
interface MyStyle extends CssResource {
String normal();
String readonly();
}
#UiField MyStyle style;
/* ... */
void setEnabled(boolean enabled) {
getElement().addStyle(enabled ? style.normal() : style.readonly());
getElement().removeStyle(enabled ? style.readonly() : style.normal());
}
}
this would allow you change style if a text box is "normal" or readonly...
And off course, in the UiBinder you should have sth like
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>
<ui:style type='com.my.app.MyFoo.MyStyle'>
.redBox { background-color:pink; border: 1px solid red; }
.normal { color:black; }
.readonly { color:gray; }
</ui:style>
<div class='{style.redBox} {style.normal}'>I'm a red box widget.</div>
</ui:UiBinder>
Try Now This One I Hope You will get it.
With the <ui:style> element, you can define the CSS for your UI right where you need it
Note: <ui:style> elements must be direct children of the root element
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:TextArea visibleLines="3" />
</ui:UiBinder>
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style field='MyStyle'>
.textBoxStyle {
background-color:yellow;
}
.textBoxStyle-readonly {
background-color:lightgray;
}
</ui:style>
<g:TextArea name="myText" styleName="{MyStyle.textBoxStyle}" visibleLines="3" />
</ui:UiBinder>
Isn't there a typo in your UIBinder?
You have:
<g:TextArea styleName="{style.textBoxStyle}" visibleLines="3" />
.. but I think you need to be using "stylePrimaryName", ie.
<g:TextArea stylePrimaryName="{style.textBoxStyle}" visibleLines="3" />
But I guess this question has been answered really already..
Here's something valuable I figured out by putting together info from other posts in this thread especially...
If you use #external, you can override gwt styles. The problem is that is this change gets applied globally! It is possible, however, to extend & override select attributes without effecting every instance of a widget type. (This like the programmatic styling method of creating a css class with a gwt class name + a suffix and using addStyleDependantName().)
Here is an example of using UIBinder + a CssResource to extend a gwt style. I left out the CssResource part, but you'll get the idea...
In your xxxx.ui.xml file, expose the gwt style, but don't mess with it!
<ui:style>
#external .gwt-Button; .gwt-Button {}
</ui:style>
Then, style a widget it by specifying 2 (or more) styles in the styleName attribute. I.e. the gwt style, and the one (or more) from your resource.
<g:Button ui:field="submitButton_" text="Submit" styleName="{style.gwt-Button} {res.loginStyles.submitButtonStyle}" />
Here's the css class:
.submitButtonStyle{
margin: 3px 5px 5px 0px;
}
In this case, I defined a button that is styled in the standard method (easily changed via module inheritance) but with a specific margin that will remain fixed. This didn't mess up the global style, it didn't require defining all the attributes manually, and allowed for swapping the global styling at will with clean.css, dark.css, etc.
I want to change the font characteristics for buttons in the toolbar of the RichTextEditor, but I want them to be different than other buttons in my application. Is there any way to do this with just CSS? I know that I can do it with setStyle if necessary...
One way to do it, since the RichTextEditor's sub-components are declared in MXML and are therefore publicly accessible, is to assign their styleName properties individually at runtime (after the container's creationComplete event fires, to be sure the editor and all its children have been created), like so:
<mx:Style>
.myRTECombo
{
color: #FF0000;
}
</mx:Style>
<mx:Script>
<![CDATA[
private function creationCompleteHandler(event:Event):void
{
rte.fontFamilyCombo.styleName = "myRTECombo";
rte.fontSizeCombo.styleName = "myRTECombo";
}
]]>
</mx:Script>
<mx:RichTextEditor id="rte" />
The Flex docs don't call out the subcomponents ("boldButton", "fontSizeCombo", et al) by ID, but the component's source is available for viewing, so you should be able to get all the info you need from the source code itself. Since I use FlexBuilder, I usually use the Eclipse Ctrl+click shortcut, on the tag/class name, to jump into the associated class-definition file, but you can also open the source file directly at [installDir]/sdks/[version]/frameworks/src/mx/RichTextEditor.mxml to have a look for yourself.
I'm sure there are other approaches (setStyle being one, although its explicit use is generally discouraged for performance reasons), but this ought to work out for you. One thing to note, though, as you'll see when you dig into the component's source, is that many of the buttons in the default button set actually use PNGs (e.g., icon_style_bold.png), not text, which is why my example includes a reference to the ComboBox instead, so you can see how the color changes apply; if you want to change the look of the buttons, be aware they're using the styleable icon property, not font-style settings, for their look and feel.
Hope it helps!
Thanks #Christian Nunciato! This is my final code, in my component that is a RichTextEditor (extends it). In the creationComplete, I call this
private function setUpStyleNames():void {
setUpStyleNamesInner(toolbar.getChildren());
setUpStyleNamesInner(toolBar2.getChildren());
}
private function setUpStyleNamesInner(children:Array):void {
for each (var child:DisplayObject in children) {
if (child is UIComponent) {
UIComponent(child).styleName = "rteInnards";
}
}
}
and then in my styleSheet, I have this
.rteInnards {
color: #FF0000;
fontSize: 25px;
}
Awesome. Thanks again!