How to use sort="auto" on A object? - groovy

I have a listheader element with sort="auto" set, but when I click the column, the list doesn't sort. The arrows appear and reverse direction, but the list order doesn't change.
The Components appended to the list are org.zkoss.zul.A objects, which appears to be the reason sorting does not work.
Is there a workaround to get sorting to work for a Listbox whose list items are A objects?
my zul:
<listbox id="myList" checkmark="true" multiple="true">
<listhead>
<listheader id='select' label="" width="30px" align="left"/>
<listheader label="myLabel" width="75px" sort="auto"/>
</listhead>
</listbox>
groovy:
Listitem li = new Listitem(value: "myId")
li.appendChild(new Listcell())
Listcell listcell = new Listcell()
Long theId = "12345"
A link = new A(label: theId.toString(), style: "color:blue;")
listcell.appendChild(invoiceLink)
li.appendChild(listcell)

I'am using MVVM approach and this is how I sort my listbox
<listbox>
<listhead>
<listheader label="Hopper" width="60px" sort="auto(hopperCode)" />
<listheader label="Stop Time" width="80px" sort="auto(startTime)" />
</listhead>
<template name="model">
<listitem>
<listcell label="#load(each.hopperCode)" />
<listcell label="#load(each.startTime)" />
</listitem>
</template>
</listbox>

According to this paragraph in the documentation, sort auto sorts by the label of the listcell. You are not using Listcell.setLabel(), but append an A component to it. Since the listcells' labels are all the same (i.e. ""), sorting doesn't do anything.
Try setting custom comparators. For this purpose I advise using a model instead of creating the listitems yourself.

Related

Add a disabled/ non-selectable separator in a bound ComboBox

I have a ComboBox and I want to add a separator which is disabled, non-selectable.
Standard functions such as add, edit, delete should be selectable under the separator.
The items containing an image and text should be displayed above the separator.
<ComboBox Name="cmbTest">
<!--These items should be loaded by code or ViewModel.-->
<ComboBoxItem >Item1</ComboBoxItem>
<ComboBoxItem >Item2</ComboBoxItem>
<ComboBoxItem >Item3</ComboBoxItem>
<!--Separator which is disabled.-->
<ComboBoxItem IsEnabled="False" >
<NavigationViewItemSeparator BorderThickness="1"></NavigationViewItemSeparator>
</ComboBoxItem>
<!--Menu below the separator.-->
<ComboBoxItem x:Name="cmbiNewApplication">Neu</ComboBoxItem>
<ComboBoxItem x:Name="cmbiEdit">Bearbeiten</ComboBoxItem>
<ComboBoxItem x:Name="cmbiDelete">Löschen</ComboBoxItem>
<ComboBoxItem x:Name="cmbiImportApplication">Import</ComboBoxItem>
<ComboBoxItem x:Name="cmbiExportApplication" >Export</ComboBoxItem>
</ComboBox>
Currently, my ComboBox is tied to a ViewModel and I've created a TemplateSelector on advice. Unfortunately, the ComboBoxItem in the template doesn't seem to be the generated ComboBoxItem itself, so the IsEnabled property has no effect.
<ComboBox x:Name="cmbApplication"
CornerRadius="3"
Width="300"
ItemsSource="{x:Bind AppProcessMainViewModel.AppProcesses}"
Tapped="cmbApplication_Tapped" >
<ComboBox.ItemTemplateSelector>
<local:MenuDataTemplateSelector>
<local:MenuDataTemplateSelector.DefaultTemplate>
<DataTemplate x:DataType="local:AppProcess" >
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Opacity="{x:Bind BoolToOpacity(Activated), Mode=OneWay}">
<TextBlock Text="{x:Bind Description, Mode=OneWay}"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</local:MenuDataTemplateSelector.DefaultTemplate>
<local:MenuDataTemplateSelector.MenuTemplate>
<DataTemplate x:DataType="local:AppProcess">
<ComboBoxItem IsEnabled="False" Height="22" >
<NavigationViewItemSeparator BorderThickness="1"></NavigationViewItemSeparator>
</ComboBoxItem>
</DataTemplate>
</local:MenuDataTemplateSelector.MenuTemplate>
</local:MenuDataTemplateSelector>
</ComboBox.ItemTemplateSelector>
</ComboBox>
My consideration was that I set the IsEnabled property of the item in the Tapped event of the combo box.
Unfortunately, I really can't figure out how to get the property of the ComboBoxItem by index.
How can I set the property?
Is this really the best approach (TemplateSelector and setting the property in the Tapped event)?
I've already read a lot about this and unfortunately there seems to be a lot missing in WinUI 3 in contrast to UWP/WPF that make things much easier.
I'm trying to get the item via the index and cast it, but there seems to be another problem, maybe because of the ViewModel?
Something like...
//Error
auto cb = cmbApplication().Items().GetAt(1).as<winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>();
I came across this site of the MS documentation (Find DataTemplate Generated Elements) and just tried it out, which works wonderfully... happy new year!
auto item = cmbApplication().ItemContainerGenerator().ContainerFromItem(cmbApplication().Items().GetAt(3));
item.as< winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>().IsEnabled(false);

How to etree findall() on many levels

I try to manipulate an diagrams.net (formerly draw.io) not compressed XML exported drawing.
Cables can be hooked up to elements and I want to get a cables-list.
I do a search for all cables by testing if the element has source and target attributes. Then I compare the id's of both with the full list of elements to find the connected label in value.
That works great until someone tries to add an "addon-tag". After that (even if it's deleted), the element gets wrapped in a <object> that has the id attribute but the source and target attribute stay in a child node called like this:
before:
<mxCell id="ferXMembXyNwfAPwV5vA-22" value="" style="..endless list" edge="1" parent="1" source="ferXMembXyNwfAPwV5vA-8" target="ferXMembXyNwfAPwV5vA-18">
<mxGeometry relative="1" as="geometry">
<mxPoint x="540" y="520" as="sourcePoint" />
<mxPoint x="700" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
after:
<object label="" id="ferXMembXyNwfAPwV5vA-53">
<mxCell style="..endless long list" edge="1" parent="1" source="ferXMembXyNwfAPwV5vA-42" target="ferXMembXyNwfAPwV5vA-51">
<mxGeometry relative="1" as="geometry">
<mxPoint x="660" y="340" as="sourcePoint" />
<mxPoint x="770" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
</object>
this findall works for normal mxCell formated to find id, source and target elements:
list_of_mxCell_elements = root.findall(root_node,".//*[#source][#target]")
and this for objects elements id's:
list_of_objects_elements = root.findall(root_node,".//*[#source][#target]/..")
But how can I access the mxCell element from the list_of_objects_elements, so I can get hold of source and target id's?
I found a solution by my own.
After findall 'elements' i iterate over the list of elements and just do another findall on each cable element i got.
It looks somewhat like this:
list_of_objects_elements = root.findall(root_node,'.//*[#source][#target]/..')
for cable in list_of_objects_elements:
for mxCell in cable.findall('./*[#source][#target]'):
Note the slighly different findall path:
This makes an search for source & target in <mxCells> while passing back the next higher element <object> from root.
.//*[#source][#target]/..
./*[#source][#target]
While the lower searches for source & target in only one element deeper than <object>
To me those paths are still a Mindblow.

SAPUI5 - Seach field on a table with column list items

EDIT: Silly me, was pointing at the wrong property. Should have been pointing it at ArticleDescription instead of value.
I require a search field on a table with custom list items. The table brings through the data fine, but a requirement now is to add a search field for easy searching due to sometimes the table can get large.
Following the SAPUI5 explored page, I cannot seem to get this to work.
Ideally I would like it to use the liveChange property so this is done on the fly. I've got it to the point where that's doing it's job but I'm not ring back the search data.
Any help would be appreciated.
Table image
main.view.xml
<!-- Search box -->
<SearchField liveChange="onSearch" width="100%" class="sapUiMediumMarginBottom"/>
<!-- Table -->
<Table id="stock_table" itemPress="onOrderClicked" items="{stock>/Items}" keyboardMode="Edit" showFullScreenButton="true">
<infoToolbar>
<Toolbar>
<ToolbarSpacer/>
<Label text="{ path:'stock>/CurrentDate', formatter:'.tableHeader'}"/>
<ToolbarSpacer/>
</Toolbar>
</infoToolbar>
<columns>
<Column minScreenWidth="Tablet" demandPopin="true">
<Text text="{i18n>Article}"/>
</Column>
<Column minScreenWidth="Tablet" width="10em" demandPopin="true">
<Text text="{i18n>UnitOfMeasure}"/>
</Column>
<Column minScreenWidth="Tablet" width="8em" demandPopin="true">
<Text text="{i18n>Quantity}"/>
</Column>
</columns>
<items>
<ColumnListItem class="sapUiSizeCompact">
<customData>
<core:CustomData key="mydata" value="{stock>_errorStateClass}"
writeToDom="true"/>
</customData>
<HBox>
<core:Icon src="sap-icon://message-information"
tooltip="{i18n>ArticleNumber}: {stock>ArticleNumber}"
class="sapUiSmallMarginEnd greggslightblue"/>
<Text text="{stock>ArticleDescription}"/>
</HBox>
<Text text="{stock>UnitOfMeasureDescription}"/>
<HBox>
<Input id="quantity_input" valueLiveUpdate="true" value="{stock>_Quantity}"
liveChange="onQuantityAmountChanged"
class="CanHaveInteraction green_enter" width="5rem"/>
<core:Icon src="sap-icon://message-error"
tooltip="{stock>_ErrorMessage}"
class="sapUiSmallMarginEnd greggsred input-warning-icon"
visible="{stock>_ErrorStatus}" press="onErrorIconPressed"/>
<core:Icon src="sap-icon://message-warning"
tooltip="{stock>_ErrorMessage}"
class="sapUiSmallMarginEnd greggsred input-warning-icon"
visible="{stock>_WarningStatus}"/>
</HBox>
</ColumnListItem>
</items>
</Table>
main.controller.js
onSearch : function (oEvt) {
// add filter for search
var aFilters = [];
var sQuery = oEvt.getSource().getValue();
if (sQuery && sQuery.length > 0) {
var filter = new Filter("Name", sap.ui.model.FilterOperator.Contains, sQuery);
aFilters.push(filter);
}
// update list binding
var list = this.getView().byId("stock_table");
var binding = list.getBinding("items");
binding.filter(aFilters, "Application");
}
are you sure the following line contains a valid search query:
var sQuery = oEvt.getSource().getValue();
As documented in the API https://openui5.hana.ondemand.com/#docs/api/symbols/sap.m.SearchField.html#event:liveChange you have to use the event source parameter 'newValue':
var sQuery = oEvt.getParameter("newValue");
Update
Please show your data structure as you try to filter on path 'Name'. But within the table column binding I cannot see any attribute called 'Name'. Rather you can try to filter on attribute 'ArticleDescription':
var filter = new Filter("ArticleDescription", sap.ui.model.FilterOperator.Contains, sQuery);

How to Disable ToolTip without Removing the "title" attribute [ASP.NET]

I have 3 TextBoxes
<asp:TextBox ID="txtTitle" runat="server" class="txtFields" title="Title" />
<asp:TextBox ID="txtName" runat="server" class="txtFields" title="Name" />
<asp:TextBox ID="txtDescription" runat="server" class="txtFields" title="Description" />
I'm using the watermark plugin on these 3 TextBoxes:
jQuery('.txtFields').watermark();
This is the plugin:
http://code.google.com/p/jquery-watermark/
jQuery('.txtFields').watermark();
Uses the Title Attribute of the TextBox to Show the Watermark but the problem is that this also Generates ToolTips which is something I do Not want, is there anyway to disable the tooltips without removing the title attribute?
Or is there anyway to use custom attributes with this plugin? By that I mean making the plugin use another attribute instead of the title attribute.
Thank you.
Looks like watermark will allow you to specify any text to display in there, so you're not stuck with the title. Any attribute that you could select with jQuery you could use as the watermark value. The problem with that is there are no other attributes you could add in there and still have nice compliant code. Best bet is to give them a value, assign a variable that value, unset it and add watermark. Something like:
$('input').each(function() {
var wmark = $(this).val();
$(this).val('');
$(this).watermark(wmark);
});
Try adding UseAccessibleHeader = false
like this:
<asp:TextBox ID="txtTitle" runat="server" class="txtFields" title="Title" UseAccessibleHeader = false />

How do specify a width percentage in JavaFX 2 using FXML?

I am looking for a way to say set a maxWidth size to 80% in FXML.
Much like in web development.
<VBox fx:id="testVB" prefWidth="600">
But this does not:
<VBox fx:id="testVB" prefWidth="80%">
I know that in Straight JavaFX2 non-fxml you can create insets? What is the best way to do this outside of code in FMXL?
Thanks!
Riley
I'm not sure you can. You need to use the GridPane layout component. In this component, you can specify rows and columns constraints, and in these constraints you can specify a width as a percentage. For example:
<GridPane>
<children>
<TitledPane text="testGridPane" GridPane.columnIndex="0" GridPane.rowIndex="0" />
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="80.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
This code defines a GridPane with a first column with a width of 80%. The TitledPane is set in the first cell of the first column of this GridPane, and can (because you need to be sure that the width constraints of the TitledPane match your needs) occupy 80% of the width of the GridPane.
Please note that I removed all information not relevant to your question. By the way, Oracle's Scene Builder tool is very useful to define complex FXML layout.
It seems like many answers have already been provided and they should work. However, there is a way to set percentages:
<fx:define>
<Screen fx:factory="getPrimary" fx:id="screen" />
</fx:define>
This would help you detect the dimensions of the current screen, the application is being displayed on. Now that we have the display dimensions, we can play with it in FXML as follows:
<HBox fx:id="hroot" prefHeight="${screen.visualBounds.height}" prefWidth="${screen.visualBounds.width}"> Your FXML elements inside the root... </HBox>
Note that I use visualBounds, since this would get me the available space on the screen, since I don't want an overlap with the taskbar in Windows for example. For fullscreen applications, you would just use 'bounds'.
Now, to come to your point of using percentages, you can actually play with the value of the prefheight and prefWidth. You can put calculations inside the ${}.
Optionally:
If you want to have all your elements use relative sizes, just refer to them, using their ID and width or height property, and make your calculation.
<VBox fx:id="VBSidebar" prefWidth="${hroot.width*0.15}" prefHeight="${hroot.height}"> more elements.. </VBox>
Hope this helps!
You can simulate it - basic example that simulates 50% for two cols in an HBox. You can add dummy panes to get thirds, etc.
HBox {
VBox {
static hgrow : "ALWAYS",
Label {
text : "Privacy",
alignment : "CENTER",
styleClass : ["h2", "heading"]
}
},
VBox {
static hgrow : "ALWAYS",
Label {
text : "Messages",
alignment : "CENTER",
styleClass : ["h2", "heading"]
},
Label {text:""}
}
}

Resources