Addressing in CSS in Flex: Buttons in RichTextEditor only? - css

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!

Related

Dynamically switch global CSS for Angular8 app (client branding)

I want to dynamically switch Angulars global CSS files based on which client is connecting. This will be used for client-branding purposes, including fonts, colors, photos, headers, footers, button-styles, etc.
Each client has provided us with a CSS file, which we need to integrate into our app. We have hundreds of clients.
Current solution is to try and override the CSS of individual components at load. This is bad because it adds a lot of boilerplate:
Html:
<link id="theme" rel="stylesheet" href="./assets/stylesheets/{{cclientCode}}.css">
ts:
ngOnInit() {
this.service.clientCode.subscribe(clientCode => this.clientCode = clientCode);
}
My workaround isn't working because the link html is called before the {{}} has a chance to load in the value.
I'm also not motivated to fix my workaround because its just that -a workaround. Instead, I want to implement something that works globally, without any per-component boilerplate.
What I want is the ability to dynamically switch the global Angular style for each client. So something like:
"styles": [
"src/assets/stylesheets/angular_style.css",
"src/assets/stylesheets/client_style.css"
]
Where client_style.css is served differently to each client.
I've found a solution that I think is workable. It definitely has issues though, so if anyone has their own answer, please still share!
First, I added a clientCode String field to SessionDataService, a global service I use to move component-agnostic data around my app:
export class SessionDataService {
clientCode: BehaviorSubject<String>;
constructor(){
this.clientCode = new BehaviorSubject('client_default');
}
setClientCode(value: String) {
this.clientCode.next(value);
}
}
Then, inside app.component.ts, I added a BehaviorSubject listener to bring in the value of clientCode dynamically:
public clientCode: String;
constructor(private service : SessionDataService) {
this.service.clientCode.subscribe(clientCode => this.clientCode = clientCode);
}
Next, I added a wrapper around my entire app.component.html:
<div [ngClass]="clientCode">
--> ALL app components go here (including <router-outlet>)
</div>
So at this point, I've created a system that dynamically adds client-code CSS classes to my components, including all children :)
Finally, I just have to write CSS rules:
.ClientOne p {
color: red;
}
.ClientOne .btn {
background-color: red;
}
.ClientTwo.dashboard {
height: 15%;
}
I hope this helps somebody! Essentially the "trick" here is to add a ngClass that wraps the entire app, and then justify all client-specific CSS rules with their client code.

How to dynamically generate CSS class and/or set its property

The title is not really a question it is more like an idea, I don't know what approach is best for my situation.
So, the problem. I have some 3rd party component that have some complex structure and styling. Some part of it has some predefined CSS class that I can override with CSS in my surrounding component. Something like this:
my component:
<div class="my-cmp-container">
<some-3rd-party-cmp></some-3rd-party-cmp>
</div>
3rd party component:
<div class="3rd-party-css-class">
...
</div>
For example, 3rd-party-css-class has style background-color: #f00, I can override it with .my-cmp-container .3rd-party-css-class { background-color: #fff; } etc. But. What if I need to set color dynamically, it's stored in a DB for example and I can't predefine each case in my class' CSS. I just have the color in hex.
In theory I can generate unique string to set as CSS class for every instance of some-3rd-party-cmp and somehow generate CSS in my component? I'm lost a little, what is the best approach for this?
Edit: Code sample to illustrate the situation https://stackblitz.com/edit/angular-kxdatq
What you are trying to do is the subject of this open issue about stylesheet binding in Angular. Until that feature is available, you can get what you want with a custom directive. Here is a directive that retrieves the checkbox element generated by ng-zorro-antd and applies two color attributes to it. The two colors are #Input properties and the directive implements OnChanges which allows to react to property binding changes.
#Directive({
selector: "[nz-checkbox][nz-chk-style]"
})
export class CheckBoxStyleDirective implements OnInit, OnChanges {
#Input("nz-chk-bkgnd") chkBkgndColor: string;
#Input("nz-chk-border") chkBorderColor: string;
private checkbox: HTMLElement;
constructor(private renderer: Renderer2, private el: ElementRef) { }
ngOnInit() {
this.checkbox = this.el.nativeElement.querySelector(".ant-checkbox-inner");
this.updateBackgroundColor();
this.updateBorderColor();
}
ngOnChanges(changes: SimpleChanges) {
if (changes.chkBkgndColor) {
this.updateBackgroundColor();
}
if (changes.chkBorderColor) {
this.updateBorderColor();
}
}
updateBackgroundColor() {
if (this.checkbox) {
this.renderer.setStyle(this.checkbox, "background-color", this.chkBkgndColor);
}
}
updateBorderColor() {
if (this.checkbox) {
this.renderer.setStyle(this.checkbox, "border-color", this.chkBorderColor);
}
}
}
Once the directive attribute selector nz-chk-style is applied to the 3rd party element, you can set the checkbox background and border colors with property binding as follows:
<span nz-checkbox nz-chk-style [nz-chk-bkgnd]="bkgndColor" [nz-chk-border]="borderColor" >
See this interactive stackblitz for a demo.
Not sure if you are using Angular but you tagged it, so I guess you are.
If you want to change only the color and nothing more, instead of having a .3rd-party-css-class class, you could just have your with an ng-style like so:
<some-3rd-party-cmp ng-style="{ color: your_color_hex_variable }"></some-3rd-party-cmp>
You can also define a whole object if styles and pass it.
You can also use ng-class and pass one or an array of class names what you want to put additionally on your component:
<some-3rd-party-cmp ng-class="[cls1, cls2, cls3]"></some-3rd-party-cmp>
<some-3rd-party-cmp ng-class="[3rd-party-css-class, someCondition ? 'another-class-name' : '']"></some-3rd-party-cmp>
In the classes you can define the css rules you want to apply and thats it.
With this solutions you can avoid having extra wrapper elements for styling purposes which is a nice thing.

GWT ListBox rendering different across browsers

So, I have a custom implementation of ListBox for a GWT application
Its xml code looks like this:
<g:FlowPanel addStyleNames="{style.yearRangePanel}">
<g:FlowPanel addStyleNames="{style.rangeSeparator} {style.paddingTop}">
<g:Label addStyleNames="{style.horizontalAlign}" ui:field="integerRangeDropdownLabel">Filter studies by range of enroled patients: </g:Label>
<g:Label addStyleNames="{style.prefixSpace} {style.horizontalAlign}" ui:field="startSampleSizeLabel"/>
</g:FlowPanel>
<g:FlowPanel ui:field="integerRangeDropdownFilterPanel" addStyleNames="{style.yearRangeSliderPanel} {style.paddingTop}">
<g:ListBox ui:field ="integerRangeDropdownListBox" styleName="{style.customListBox}"/>
</g:FlowPanel>
</g:FlowPanel>
And its main java code looks like:
#UiConstructor
public IntegerRangeDropdownFilterComposite (String fieldName, String labelText){
this.initWidget(uiBinder.createAndBindUi(this));
filterChangedEvent = new FilterChangedEvent(fieldName);
FilterConfig filterConfig = clientFactory.getApplicationContext().getConfig(FilterConfig.class);
List<FilterSetting> filterSettings = filterConfig.getFilterConfigBy(fieldName);
FilterSetting filterSetting = filterSettings.get(0);
filterByIntegerRangeSettings = (FilterConfig.FilterByIntegerRangeSettings) filterSetting;
this.increment = Integer.toString(filterByIntegerRangeSettings.getIncrement());
this.minSampleSize = Integer.toString(filterByIntegerRangeSettings.getInitialValue());
this.maxSampleSize = Integer.toString(filterByIntegerRangeSettings.getEnd());
this.setupConfig(fieldName);
}
private void setupConfig(String fieldName){
setupRange(fieldName);
}
#Override
protected void onLoad() {
super.onLoad();
integerRangeDropdownFilterPanel.add((Widget) integerRangeDropdownListBox);
}
public void resetIntegerRangeDropdownFilter() {
filterChangedEvent.resetField();
}
#UiHandler("integerRangeDropdownListBox")
public void clickEnroled(ChangeEvent changeEvent){
if(integerRangeDropdownListBox.getSelectedIndex()!=0) {
String selectedItem = integerRangeDropdownListBox.getSelectedItemText();
minSampleSize = selectedItem.substring(0, (selectedItem.indexOf('-'))).trim();
maxSampleSize = selectedItem.substring((selectedItem.indexOf('-') + 1)).trim();
}
else{
minSampleSize="0";
maxSampleSize="100000";
}
resetIntegerRangeDropdownFilter();
filterChangedEvent.addFilter(Integer.parseInt(minSampleSize), Integer.parseInt(maxSampleSize));
clientFactory.getEventBus().fireEvent(filterChangedEvent);
}
Now, as for the style, I've tried "bootstrapping" it with this line:
<g:ListBox ui:field ="integerRangeDropdownListBox" styleName="btn btn-primary dropdown-toggle"/>
And I've tried customizing it with CSS like this:
.customListBox{
background-color: dodgerblue !important;
color: white;
padding: 5px;
}
<g:ListBox ui:field ="integerRangeDropdownListBox" styleName="{style.customListBox}"/>
Whichever way I do it, it will not render equally across browsers, it only looks "nice" on Google Chrome, while in Safari and Firefox it will have an "uglee" arrow for the dropdown and different scroll bar.
Any ideas as for why this may be happening? Needless to say I've tried google and the forum, but searching for GWT related topics is pretty much useless
First, you should use addStyleNames instead of styleName, because styleName removes all existing style names and replaces them with the style name you provided.
Second, this is not a GWT problem. Browsers render various elements differently. If you want a more uniform look, you need to search for CSS suggestions.
It is exactly as you described your question: The standard GWT ListBox is rendering different across browsers.
The main reason is that it is using a native browser control under the hood.
It creates a HTML select control element here.
You can try that basic HTML control yourself in different browsers here.
So there is not much you can do about that.
On some browser you might be able to style it, but not consistently.

Add custom style property to MXML Custom Component

I have a Custom Component that has a couple of Canvas with some background colors assigned to them. Now i have hard coded the colors, i want to move them to an external css file.
So i would like to have the css declaration like this :
ControlBar
{
dividerRightColor: #ffffff;
dividerLeftColor: #f3f3f3;
}
My question is if i can define custom style names like dividerRightColor and if so, how can i use that value inside my MXML Component? I have seen examples of using them inside Pure AS components.
In CSS:
.dividerRightColor {
background-color: #ffffff;
}
.dividerLeftColor {
background-color: #f3f3f3;
}
In MXML:
<mx:ControlBar>
<mx:Canvas styleName="dividerLeftColor">
…
</mx:Canvas>
<mx:Canvas styleName="dividerRightColor">
…
</mx:Canvas>
</mx:ControlBar>
It sounds to me like you need to create the style in the component; not just send the style values into the component as the other answer.
Read this documentation.
Basically, styles don't get defined the same way that properties get defined. You can set any style name on the component you want. However, the component needs to know what to do w/ the style. To do that you need to override the styleChanged method:
override public function styleChanged(styleProp:String):void {
super.styleChanged(styleProp);
// Check to see if style changed.
if (styleProp=="dividerRightColor")
{
// do stuff to implement the style
dividerRight.setStyle('backgroundColor',getStyle('dividerRightColor'));
}
}
A common approach is to set "styleChanged" properties and invalidate the display list and then make the appropriate style changes in the updateDisplayList() method.
To make the style available in code hinting, you'll need to add metadata, like this:
[Style(name="dividerRightColor")]
This will only be required if you wish to set the style as a property in MXML.

Applying styles for custom TextArea in ActionScript 3

I have the following code to create and apply a few styles for a custom TextArea in ActionScript 3.
public class MyCustomTextArea extends TextArea
{
override protected function createChildren():void
{
super.createChildren();
this.styleSheet.setStyle("sup", { display: "inline", fontFamily: "ArialSup", fontSize:"12"});
this.styleSheet.setStyle("sub", { display: "inline", fontFamily: "ArialSub", fontSize:"12"});
this.setStyle("fontFamily", "Arial");
}
}
I have two problems with this code.
this.styleSheet is always null when I create an instance of the class. If this.styleSheet is initialized to new StyleSheet() to avoid this issue, then the TextArea instance does not seem to recognize any of the HTML tags that can be used with the htmlText property.
Can anyone help in fixing these two issues? Thanks.
First off - the styleSheet property of a TextArea component is null by default - what you're seeing is an expected behavior.
You're also creating your css stylesheet in an unusual way - perhaps this is where your problems are coming from? I'd try either loading, or defining inline, a stylesheet to apply to your text area. There's an example of loading and applying a stylesheet here: http://blog.flexexamples.com/2008/03/22/applying-a-cascading-style-sheet-to-a-textarea-control-in-flex/
Also, what are ArialSub and ArialSup? If these aren't valid font names flex won't recognize them and use them.

Resources