I need a ComboBox without this clear button. It confuses the users.
I believe in Vaadin 8 it could be removed with setEmptySelectionAllowed(true);.
How can it be removed in vaadin 10? setAllowCustomValue(false) does not help.
Java 8
Vaadin 10.0.2
I guess the easiest way to achieve that would be with CSS, at least that's how I would do it.
What you want to do is extend the default theme module for VaadinComboBox web component (see https://github.com/vaadin/vaadin-themable-mixin/wiki/2.-Adding-Styles-to-Local-Scope), so you can use the following approach:
First, choose a CSS class name, like my-combobox
Next, create an HTML file that will contain the extension of the default theme module for VaadinComboBox web component. Give it a name like my-combobox-theme.html and put it into src/main/resources/META-INF/resources (yes, it's resources twice)
Put the following into that HMTL file:
<dom-module id="my-combobox-theme" theme-for="vaadin-combo-box">
<template>
<style>
:host(.my-combobox) [part="clear-button"] {
display:none !important
}
</style>
</template>
</dom-module>
In the first line you declare that the following CSS is supposed to supplement whatever styles are defined for VaadinComboBox web component.
Then, the only CSS rule that is there defines that whenever there is a VaadinComboBox that has CSS class my-combobox the clear-button part of the web component should not be displayed.
Import the custom module to a view with #HtmlImport("frontend://my-combobox-theme.html"). NB: you need to add this annotation in all views that you want to use the modified ComboBox in. See point 6 for an alternative
Now you're pretty much all set. Whenever you want to have a ComboBox without delete button, just add a class name with comboBox.addClassName("my-combobox")
You probably want to use your ComboBox in more than one place, so a good idea is to create your own class. This gives you a reusable component and takes care of always having the right HTML import for custom style in place:
#HtmlImport("frontend://my-combobox-theme.html")
public class MyCombobox extends ComboBox {
public MyCombobox() {
addClassName("my-combobox");
// Adding the following code registers a listener which
// resets the old value in case the user clears the
// combo box editor manually, e.g. by entering "".
//
// addValueChangeListener(listener -> {
// if(listener.getValue() == null) {
// setValue(listener.getOldValue());
// }
// });
}
}
Since Vaadin 14 you can easily hide/show the clear button with
comboBox.setClearButtonVisible(false);
API documentation
I know you asked for Vaadin 10, but for completeness I wanted to add this here.
This is not possible at the moment but discussed as feature. See the Github issue No way to disallow clearing selected value. You can leave a thumbs up on that issue to emphasize its importance. IMO this is a must-have feature that should be implemented from the beginning.
The roadmap says something about a "Dropdown menu" upcoming in Vaadin 11 in Q3. This could be interesting.
I am using shadow-dom traversal of the clear button component inside the vaadin-combo-box (in this case, id:my-combo), and set the display property. (javascript)
var clear_button = this.$.my_combo.shadowRoot.querySelector("#clearButton");
clear_button.style.display = "none";
Related
I'm currently using Angular2 (Dart) to create a reusable search box component, which includes a suggestion box.
The trouble I'm running into is that I'm not sure how to make the suggestion box extensible by supporting richer suggestion types, such as suggestions with icons, suggestions with multiple lines of text, varying styles on the text, animations, etc.
Currently the suggestion box HTML (stripped down) looks a bit like this:
<div class="suggestion-box-container">
<div class="suggestion" *ng-for="#suggestion of model.suggestions">
{{ suggestion.text }}
</div>
</div>
And the Dart code looks sort of like this:
#Component(
selector: 'suggestion-box'
)
#View(
templateUrl: 'suggestion_box.html',
directives: const [NgFor]
)
class SuggestionBox {
final SuggestionModel model;
// ...
}
class SuggestionModel {
List<Suggestion> suggestions = [];
// ...
}
class Suggestion {
String text;
// ...
}
I'm wondering how I can modify this design so that a user can extend Suggestion and write their own corresponding suggestion component.
I considered something like
<basic-suggestion *ng-if="suggestion.type == 'basic'"></basic-suggestion>
<icon-suggestion *ng-if="suggestion.type == 'icon'"></icon-suggestion>
...
But of course that would get out of hand quickly as more suggestion types are supported, and would also require duplicating the (^hover) and (^click) handlers to each type of suggestion. Worse yet, it would require modifying the original library rather than just using it in a modular way.
Is there an elegant solution to this sort of thing? Or would users simply be better off writing their own suggestion box entirely if they wanted richer suggestions? I'm hoping to avoid that since I want to bake in a bunch of accessibility functionality into the search box/suggestion box that the user shouldn't need to rewrite.
EDIT: based on Gunter's answer I've managed to improve this by a little bit:
<suggestion-box>
<div *ng-for="#suggestion in suggestions">
<suggestion suggestion-instance="suggestion">
<!-- Custom suggestion code goes here.
The following is an example -->
<img src="{{suggestion.iconSrc}}"></img> {{suggestion.text}}
</suggestion>
</div>
</suggestion>
I have a new suggestion component that looks a bit like this:
#Component(
selector: 'suggestion',
properties: const ['suggestion: suggestion-instance']
)
#View(
template: '''
<div (^click)="handleClick(suggestion)"
(hover)="handleHover(suggestion)">
<content></content>
</div>
'''
)
class SuggestionComponent {
final SuggestionModel model;
final Suggestion suggestion;
// ...
}
This is a bit nicer now because the user now gets accessibility/keyboard control/mouse control out of the box. But this still isn't ideal. I'd somehow like the template to automatically determine the appropriate component to use based on the actual subclass of the suggestion. I suppose I could define a method in each component like getTemplate() but that probably wouldn't be a very Angular-esque way of doing it.
I haven't really used Angular2 but I think there are at least two ways to do it
- You should be able to extend a component (just create a derived class and specialize the behavior
- Use composition with the <content> tag of the shadow DOM. I found some docs here https://www.airpair.com/angularjs/posts/creating-components-p3-angular2-directives
- Or a combination of the two
update
Support for extending components is coming with version 3.2.
Annotations like #HostBinding(), #HostListener(), #ViewChild(), #ContentChild() will be recognised on subclasses, so will be interfaces for OnInit and other lifecycle callbacks
There are different ways beside inheritanc to make a component customizable.
You can pass component types to be instantiated by your search box using DynamicComponentLoader,
pass children to be displayed at <ng-content> locations,
or pass <template> content to be added dynamically by your search component, and probably others.
I'm learning Dart by making a simple webapp. the app ui I have in mind has two parts, one is a control panel, the other is a workspace. by clicking buttons in the control panel, user should be able to control the workspace.
both the control panel and the workspace are custom polymer elements. In the Control Panel's dart class, I can access itself by using shadowRoot.querySelector, but since the control panel needs to control the workspace, I need to access the workspace also. but I don't know how to do that. I tried querySelector for example, It gave me null. I understand it is a shadow DOM in the workspace tag, but how to access other tags' shadow DOM?
I can't find anything online, every example and document seems to only use shadowRoot to access self elements.
It is difficult to access the shadow DOM of another element, and this is by design. Instead of having your two custom elements so tightly coupled, a better approach would be to use events or signals. Your control panel element should take user input and fire appropriate events using the convenient fire() method it inherits from the PolymerElement class. Your application can catch and then relay those events to your workspace element. If that seems overly circuitous, you can use Polymer's <core-signals> element to pass events without dealing with intermediaries.
As an example, inside your control panel element, you might have a bold button.
<button on-click="{{boldClicked}}">Bold</button>
When that button is clicked, the control panel's boldClicked() method is executed in response. It might look something like this:
void boldClicked(Event event, var detail, Element target) {
fire('core-signal', detail: {'name': 'bold', 'data': null});
}
Then in your workspace element's HTML file, you might have:
<core-signals on-core-signal-bold="{{boldEventReceived}}"></core-signals>
And finally, in your workspace element's Dart class would be a method like so:
void boldEventReceived(Event event, var detail, Element sender) {
// manipulate workspace shadow DOM here
}
This is just one of several ways to accomplish this. You can look over the Dart team's <core-signals> example for more.
And of course, if you're using Polymer to its full potential, you will find that you need to do very little manual DOM manipulation. Using data binding and data-driven views is a winning strategy.
You can either use a selector that pierces though all shadow boundaries querySelector('my-tag /deep/ some-element') or querySelector('* /deep/ some-element') or as selector that just pierces through one level of shadow boundary querySelector('my-tag::shadow some-element') or alternatively
place both elements within the <template> of another Polymer element then you can connect attributes of both components with the same field on the common parent element (this is the preferred method in Polymer.
The solution of #user3216897 is fine of course especially if the elements don't share a common parent.
Instead of shadowRoot.querySelector you should be able to use $['abc'] if the element has an id attribute with the value 'abc'.
I am newbie to Xamarin and Xamarin.Form, basically I want to define style for the controls.
Like when I place Label control then it should follow the same style throughout the page. I've read somewhere on article that it can be done by defining styles in tags but don't know how..
How to define for 1 page
How to define globally which will be applied to all the pages
How to define device specific
Can anyone provide some example code / link for same?
Thanks in advance!
If you are talking about doing it through XAML then:
- if it is per page then go with resources.
- for device specific, use OnPlatform class
- there are no global resources currently
If you are creating your stuff in code then apply whatever global value you wish when you create them. If there are platform specific values then use Device class.
HTH
For per page resources, you can create a Common folder with files such as "ColorResources" which might have entries such as
public static readonly Color ActivityIndicator = Color.Blue;
You can then use that in your XAML like this
<ActivityIndicator IsRunning="{Binding IsLoading}"
Color="{x:Static common:ColorResources.ActivityIndicator}" />
(Remember to declare your common namespace)
For cross page, I'd recommend a custom renderer, built from the original control but tailored to look like what you want. You can find out more hereCustom Renderers
In (latest) Dart Web UI, what's the best way to process an element when it's added or removed from the DOM by a template? Ideally I'd like to register a callback right in the template, but that's not a requirement.
Background: I need to register/unregister certain DOM elements from two JS libraries (one of which is a JQuery plugin). Since my template uses loops and conditionals (and data binding), elements can come and go at any time, and I can't just register them after the initial rendering.
It is possible to add callbacks to your component's class that trigger when it is either created, inserted into the DOM, or removed from the DOM.
Web UI Specification: Lifecycle Methods
class MyComponent extends WebComponent {
inserted() {
// Do stuff when inserted into DOM.
}
removed() {
// Do stuff when removed from DOM.
}
}
I would like to build a new component on the basis of PrimeFaces Tab/Tabview components. It should look like an add tab in a browser and open a page for filling out a form. The problem is that I want to integrate it in a TabView based on a data model (http://www.primefaces.org/showcase/ui/tabviewModel.jsf). Right now I can either combine a tab for filling out a form with a tab with predefined data or use a TabView, which dynamically creates tabs for my data.
I have read JSF documentation about creating custom components in two ways - as composite component or as a new Java class. I tried to create a custom component but it does not seem to work the way I described beyond.
My questions are:
1) is it possible to solve this problem with a composite component? If yes, could someone give me a hint?
2) if not, is there a tutorial for writing a new component on the basis of existing PrimeFaces component (presumably new sort of TabView)?
UPD: After doing some research I realized that the easiest way is writing a new renderer for TabView.
I declared a new renderer class:
public class AddableTabViewRenderer extends TabViewRenderer
and registered it in faces-config.xml:
<render-kit>
<render-kit-id>HTML_BASIC</render-kit-id>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.TabView</renderer-type>
<renderer-class>
de.idealo.evaluation.jsf.webapp.component.AddableTabViewRenderer
</renderer-class>
</renderer>
</render-kit>
However, when a view with TabView component is rendered, the encodeEnd method of TabViewRenderer is called, not the overriden method of AddableTabViewRenderer.
Can you give me a hint about where the problem might be?
The renderer-class is wrong in my configuration. I misunderstood the instructions about registering a component. I thought that render-type is the class that will be rendered with the custom renderer. It must be org.primefaces.component.TabViewRenderer instead. Now it works fine :)