I have following code:
var pickerViewModel = new MvxPickerViewModel(this.mandantenPicker);
this.mandantenPicker.Model = pickerViewModel;
this.mandantenPicker.ShowSelectionIndicator = true;
mandantenAuswahlTextfield.InputView = this.mandantenPicker;
var set = this.CreateBindingSet<LoginView, LoginViewModel>();
set.Bind(pickerViewModel).For(p => p.SelectedItem).To(vm => vm.SelectedMandant);
set.Bind(pickerViewModel).For(p => p.ItemsSource).To(vm => vm.Mandanten);
set.Apply();
In the PickerView I don't have the expected values. Its showing the namespace of the object.
I'm binding to a list of "Mandants", a Mandant has FirstName/LastName. How can I set the "to be showed" value?
So something like:
set.Bind(pickerViewModel).For(p => p.ItemsSource).To(vm => vm.Mandanten)["FirstName"]; //stupid example but to show better what I mean/want
The MvxPickerViewModel currently uses GetTitle() to work out what to display:
public override string GetTitle(UIPickerView picker, int row, int component)
{
return _itemsSource == null ? "-" : RowTitle(row, _itemsSource.ElementAt(row));
}
protected virtual string RowTitle(int row, object item)
{
return item.ToString();
}
from https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxPickerViewModel.cs
If you wanted to customise the strings displayed, you could:
inherit from MvxPickerViewModel and provide an override for RowTitle:
protected override string RowTitle(int row, object item)
{
return ((Mandant)item).FirstName;
}
or override the ToString in your Mandant object
or provide and use some ValueConverters from IEnumerable<Mandant> to IEnumerable<WrappedMandant> and Mandant to WrappedMandant where WrappedMandant provides the ToString() implementation you want to use:
public class WrappedMandant
{
public Mandant Mandant { get;set;}
public override string ToString()
{
return Mandant.FirstName;
}
}
If you wanted to customise the picker cells displayed further, then you could also override GetView and them provide a custom cell for each Mandant
Related
I want to create a custom lightning component to create new Case records and need to use fieldset to include fields in component. Need to use this only for one object. I never used fieldsets so dont have any idea on it. It would be really great if you can share some sample code or any link for the same.
You can use this utility class
This is the wrapper class to hold the meta info about the fields
public with sharing class DataTableColumns {
#AuraEnabled
public String label {get;set;}
#AuraEnabled
public String fieldName {get;set;}
#AuraEnabled
public String type {get;set;}
public DataTableColumns(String label, String fieldName, String type){
this.label = label;
this.fieldName = fieldName;
this.type = type;
}
}
Class FieldSetHelper has a method getColumns () this will return the list of DataTableColumns wrapper containing the information about the filedset columns
public with sharing class FieldSetHelper {
/*
#param String strObjectName : required. Object name to get the required filed set
#param String strFieldSetName : required. FieldSet name
#return List<DataTableColumns> list of columns in the specified fieldSet
*/
public static List<DataTableColumns> getColumns (String strObjectName, String strFieldSetName) {
Schema.SObjectType SObjectTypeObj = Schema.getGlobalDescribe().get(strObjectName);
Schema.DescribeSObjectResult DescribeSObjectResultObj = SObjectTypeObj.getDescribe();
Schema.FieldSet fieldSetObj = DescribeSObjectResultObj.FieldSets.getMap().get(strFieldSetName);
List<DataTableColumns> lstDataColumns = new List<DataTableColumns>();
for( Schema.FieldSetMember eachFieldSetMember : fieldSetObj.getFields() ){
String dataType =
String.valueOf(eachFieldSetMember.getType()).toLowerCase();
DataTableColumns datacolumns = new DataTableColumns(
String.valueOf(eachFieldSetMember.getLabel()) ,
String.valueOf(eachFieldSetMember.getFieldPath()),
String.valueOf(eachFieldSetMember.getType()).toLowerCase() );
lstDataColumns.add(datacolumns);
}
return lstDataColumns;
}
}
After you getting all those field set information the create lightning component dynamically
I have to use a combobox to associate a list of values (key, Value). Key is the value to be stored in the database, Value is the description to be displayed in the combobox.
For example:
Key / value
C1 Code one
C2 Choice two
C3 Choice three
...
Retrieving, for example, the selected value 'Choice two' I would like to receive the code C2.
For storing the elements in items I defined the ComboVal class.
Defining my combobox, I am stuck on the definition of the setConverter function.
The compiler gives me the following error:
Error: (1093, 49) java: constructor FormatStringConverter in class javafx.util.converter.FormatStringConverter cannot be applied to given types; required: java.text.Format; found: no arguments
reason: actual and formal argument lists differ in length
Code:
class ComboVal {
String[] dato = {null, null};
ComboVal (String Key, String Value)
{
setValue(Key, Value);
}
ComboVal ()
{
setValue(null, null);
}
String getValue ()
{
return dato[1];
}
String getKey ()
{
return dato[0];
}
void setValue (String Key, String Value)
{
dato[0] = Key;
dato[1] = Value;
}
}
classe myclass {
....
/*
Parameter ctrl is a List containing information for dynamic creation of combobox
*/
void mothod (List ctrl)
{
VBox box = new VBox();
box.getChildren().add(new Label(ctrl. label));
ObservableList items = FXCollections.observableArrayList();
ComboBox<ComboVal> cb = new ComboBox<>();
cb.setId(ctrl.name);
cb.setItems(items);
//----->>> compiler report error in the next row <<<<<<<<
cb.setConverter(new FormatStringConverter<ComboVal>() {
#Override
public String toString (ComboVal object)
{
return (object.getValue());
}
#Override
public ComboVal fromString (String string)
{
return null;
}
});
ctrl.options.forEach((k, v) -> {items.add(new ComboVal(k, v));});
cb.setCellFactory(new Callback<ListView<ComboVal>, ListCell<ComboVal>>() {
#Override
public ListCell<ComboVal> call (ListView<ComboVal> p)
{
return new ListCell<ComboVal>() {
#Override
protected void updateItem (ComboVal item, boolean empty)
{
super.updateItem(item, empty);
if (item == null || empty)
{
setGraphic(null);
}
else
{
setGraphic(new Text(item.getValue()));
}
}
};
}});
box.getChildren().add(cb);
}
The FormatStringConverter class needs to be constructed with a Format parameter. You however constructed it with no parameters.
Supply a Format, like this for example:
Format format = new MessageFormat("Bla bla");
cb.setConverter(new FormatStringConverter<ComboVal>(format);
The FormatStringConverter defines its own toString and fromString methods already, and will use the given format to parse and display the values. I doubt this is what you want as this is pretty limited.
So I think you'd be better of just using a regular StringConverter and provide the custom implementations for toString and fromString.
Hi I want to make a "Query" and put a filter for returning all pages that has "Show on a menu" checked. I did not find a way to do that.. Is it possible?
Try something like this:
using Orchard.Localization;
using Orchard.Projections.Descriptors.Filter;
using Orchard.Navigation;
using IFilterProvider = Orchard.Projections.Services.IFilterProvider;
namespace MyProject.Filters
{
public class MenuPartFilter : IFilterProvider {
public Localizer T { get; set; }
public ProductPartFilter() {
T = NullLocalizer.Instance;
}
public void Describe(DescribeFilterContext describe)
{
describe.For(
"Content", // The category of this filter
T("Content"), // The name of the filter (not used in 1.4)
T("Content")) // The description of the filter (not used in 1.4)
// Defines the actual filter (we could define multiple filters using the fluent syntax)
.Element(
"MenuParts", // Type of the element
T("Menu Parts"), // Name of the element
T("Menu parts"), // Description of the element
ApplyFilter, // Delegate to a method that performs the actual filtering for this element
DisplayFilter // Delegate to a method that returns a descriptive string for this element
);
}
private void ApplyFilter(FilterContext context) {
// Set the Query property of the context parameter to any IHqlQuery. In our case, we use a default query
// and narrow it down by joining with the MenuPartRecord.
context.Query = context.Query.Join(x => x.ContentPartRecord(typeof (MenuPartRecord)));
}
private LocalizedString DisplayFilter(FilterContext context) {
return T("Content with MenuPart");
}
}
}
Is there a way to store an identifier of a model object or the model object itself in a JavaFX 2 TreeItem<String>? There is just Value to store the text...
I'm populating a TreeView from a list of model objects, and need to find it when the user clicks a node. I'm used to work with Value and Text in .NET Windows Forms or HTML and I am afraid I cannot adapt this way of thinking to JavaFX...
You can use any objects with TreeView, they just have to override toString() for presenting or extend javafx.scene.Node
E.g. for next class:
private static class MyObject {
private final String value;
public MyObject(String st) { value = st; }
public String toString() { return "MyObject{" + "value=" + value + '}'; }
}
TreeView should be created next way:
TreeView<MyObject> treeView = new TreeView<MyObject>();
TreeItem<MyObject> treeRoot = new TreeItem<MyObject>(new MyObject("Root node"));
treeView.setRoot(treeRoot);
I have the same issue as the OP. In addition I want to bind the value displayed in the TreeItem to a property of the object. This isn't complete, but I'm experimenting with the following helper class, where I'm passing in the "user object" (or item) to be referenced in the TreeItem, and a valueProperty (which, in my case, is a property of the item) to be bound to the TreeItem.value.
final class BoundTreeItem<B, T> extends TreeItem<T> {
public BoundTreeItem(B item, Property<T> valueProperty) {
this(item, valueProperty, null);
}
public BoundTreeItem(B item, Property<T> valueProperty, Node graphic) {
super(null, graphic);
itemProperty.set(item);
this.valueProperty().bindBidirectional(valueProperty);
}
public ObjectProperty<B> itemProperty() {
return itemProperty;
}
public B getItem() {
return itemProperty.get();
}
private ObjectProperty<B> itemProperty = new SimpleObjectProperty<>();
}
Is there any way to check declaratively whether an enum has a specified value. For example:
<h:graphicImage name="error.png" library="images"
rendered="#{viewController.current.status == Status.ERROR}" />
It's a little bit tedious to define a method in the managed beand that checks this for every enum value, e.g.
public boolean isStateIsError() {
return current.getStatus() == Status.ERROR;
}
Is there a shorter/better way of doing this?
Until EL 3.0 it's not possible to import enums in EL scope. You can however just treat and compare them like strings, i.e. the enum constant value must be quoted like below.
<h:graphicImage name="error.png" library="images"
rendered="#{viewController.current.status eq 'ERROR'}" />
I know this question is a bit older now, but i had the same problem and found another solution, which i want to share :
Create a Custom EL-Resolver and use enums and java constants as objects in jsf el:
<h:graphicImage name="error.png" library="images"
rendered="#{viewController.current.status == Status.ERROR}" />
But before you can use enums this way you have to do 3 steps.
1. step - Copy this Class and replace "MY_ENUM" through your enumClass (in the example above it would be "Status")
public class EnumCache {
private Map<String, Object> propertCache = new HashMap<String, Object>();
private Map<String, Class> baseCache = new HashMap<String, Class>();
private static EnumCache staticEnumCache = null;
public static EnumCache instance() {
if (staticEnumCache == null) { staticEnumCache = new EnumCache(); }
return staticEnumCache;
}
private EnumCache() {
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(MY_ENUM.class);
for(Class clazz : classes) {
try {
baseCache.put(clazz.getSimpleName(), clazz);
Method m = clazz.getMethod("values", (Class[]) null);
Enum<?>[] valueList = (Enum[]) m.invoke(null, (Object[]) null);
for (Enum<?> en : valueList) {
propertCache.put(clazz.getSimpleName() + "." + en.name(), en);
}
} catch (Exception e) {
System.err.println(clazz.getSimpleName(), e);
}
}
}
public Object getValueForKey(String key) {
return propertCache.get(key);
}
public Class getClassForKey(String key) {
return baseCache.get(key);
}
}
2. step - add this EnumResolver - This class will map your JSF expression to the enum in cache (step 1)
public class MyEnumResolver extends ELResolver {
public Object getValue(ELContext context, Object base, Object property) {
Object result = null;
if (base == null) {
result = EnumCache.instance().getClassForKey(property + "");
} else if (base instanceof Class) {
result = EnumCache.instance().getValueForKey(((Class) base).getSimpleName() + "." + property);
}
if (result != null) {
context.setPropertyResolved(true);
}
return result;
}
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
return null;
}
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
public boolean isReadOnly(ELContext context, Object base, Object property) {
return false;
}
public void setValue(ELContext context, Object base, Object property, Object arg3) {
}
}
3. step - register the EnumResolver in faces-config.xml
<faces-config>
<application>
<el-resolver>com.asd.MyEnumResolver</el-resolver>
</application>
</faces-config>
NOTE:
If you want to access your java constants this way, you just have to extend the constructor of the enumCache class.
This (untestet) example should work:
baseCache.put(CLASS_WITH_CONSTANTS.getSimpleName(), clazz);
for (Field field : CLASS_WITH_CONSTANTS.getDeclaredFields()) {
try {
propertCache.put(CLASS_WITH_CONSTANTS.getSimpleName() + "."
+ field.getName(), field.get(null));
} catch (Exception e) { }
}
Hope this reduced but working code can help anybody.
Update
I see this benefits:
If you use strings in jsf (viewController.current.status == 'ERROR_abcdefg'), you can misspell the value and wont recognise it so fast.
With my solution you would get an error while loading the jsf file, because the enum could not be resolved.
You can see in the sourcecode that "ERROR" is value of the enum "STATUS".
When you compare two values in el, the class of the enums will be compared too.
So for example PersonState.ACTIV is not the same like AccounState.ACTIV.
When i have to change my enum value from PersonState.ACTIV to PersonState.ACTIVATED i can search for the String "PersonState.ACTIV" in my sourcecode. searching for "ACTIV" would have much more matches.
I solved a similar problem by statically dumping all the enum keys (which are used in the rendered UI components) in a map and then I use a static getByKey method to convert the value from the UI into an actual native enum in the setter, throwing an Exception if the value provided is invalid:
public enum ReportType {
FILING("F", "Filings"),
RESOLUTION("R", "Resolutions"),
BASIS("B", "Bases"),
STAFF("T", "Staff Counts"),
COUNTS("I", "Counts");
private String key;
private String label;
private static Map<String, ReportType> keyMap = new HashMap<String, ReportType>();
static {
for(ReportType type : ReportType.values()) {
keyMap.put(type.getKey(), type);
}
}
private ReportType(String _key, String _label) {
this.key = _key;
this.label = _label;
}
public String getKey() {
return this.key;
}
public String getLabel() {
return this.label;
}
public static List<ReportType> getValueList() {
return Arrays.asList(ReportType.values());
}
public static ReportType getByKey(String _key) {
ReportType result = keyMap.get(_key);
if(result == null) {
throw new IllegalArgumentException("Invalid report type key: " + _key);
}
return result;
}
}
In the UI tier, the enum key is used as the value and the enum label is used as the label:
<f:selectItems var="rptTypeItem" value="#{reportController.allReportTypes}"
itemLabel="#{rptTypeItem.label}" itemValue="#{rptTypeItem.key}"/>
In the managed bean, I convert the enum into a renderable list, using the getValueList() from the enum:
public List<ReportType> getAllReportTypes() {
return ReportType.getValueList();
}
Finally, the [g|s]etters in the managed bean look as follows:
public String getReportType() {
return this.crtRptType.getKey();
}
public void setReportType(String _val) {
this.crtRptType = ReportType.getByKey(_val);
}
I think it could be done it the following way:
Create a method in you bean that would return the list of enums, for example
public Status[] getStatuses() {
Status.values();
}
then you can use the enum in EL like this
<h:graphicImage name="error.png" library="images"
rendered="#{viewController.current.status == someBean.statuses[0]}" />
assuming that the order of enum members is not going to be changed (for ex. here statuses[0] is ERROR). However, I would fix the positions like this:
public Status[] getStatuses() {
Status myStatuses = new Status [2]; // or whatever number of statuses you are going to use in UI
myStatuses [0] = Status.ERROR;
myStatuses [1] = Status.RUNNING;
return myStatuses;
}
This is still not dynamic solution, but it's better than hard-coding in EL. Might be especially useful when you'r using localization for you statuses (enum values depending on locale/translation).