Updating Griffon JavaFX combo boxes - combobox

I'm trying to update the content of a combo box (using Griffon 1.2.0, with the JavaFX plugin).
My model:
class MyModel {
List monthList = FXCollections.observableList([new DateMidnight()])
def convertDate = [
fromString: { String s ->
return new DateMidnight(DateTimeFormat.forPattern("yyyy-MM").parseDateTime(s))
},
toString: { DateMidnight d ->
return "2011-10"
}
] as StringConverter
}
My view contains:
comboBox(items: (model.monthList), converter: model.convertDate)
Now I have a controller action which gets invoked when they push a button:
def load = {
execInsideUIAsync {
def months = myService.buildMonthList()
model.monthList.addAll(months)
}
}
The problem is that the combo box content never changes. Can anyone help me understand what I'm missing?
There's no documentation on ComboBox yet http://groovyfx.org/docs/guide/single.html#choiceBoxComboBox
Also, have I implemented the converter correctly?

The problem is that GroovyFX.comboBox creates a new List instead of using the one you pass as argument for items: This problem occurs with tableView as well. A temporary workaround would be to set the items property directly, like this
comboBox(id: 'combo')
noparent { combo.items = model.monthList }

Related

Grid with LitTemplate not updating checkbox consistently

We are updating our Grid forms to use LitTemplates for rendering. However we have run into an issue with a checkbox state not being updated even though the underlying data for the state has been updated. The following code demonstrates the issue:
HorizontalLayout hlTest = new HorizontalLayout();
List<String> selected = new ArrayList<>();
Grid<String> testGrid =new Grid<>();
testGrid.setWidth("250px");
testGrid.setHeight("250px");
List<String> dataList = new ArrayList<>(List.of("AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE"));
ListDataProvider<String> dataProvider = new ListDataProvider<>(dataList);
testGrid.setItems(dataProvider);
String template = """
<vaadin-checkbox #click="${handleCheckClick}" ?checked="${item.rowSelected}"></vaadin-checkbox>
<div>${item.text}</div>
""";
LitRenderer<String> lit = LitRenderer.of(template);
lit.withProperty("rowSelected", item -> {
boolean rc = selected.contains(item);
System.out.println("Item selected: " + item + " => " + rc);
return rc;
});
lit.withProperty("text",item -> item);
lit.withFunction("handleCheckClick", (item) -> {
if(selected.contains(item))
selected.remove(item);
else
selected.add(item);
});
testGrid.addColumn(lit);
Button bSelect = new Button("Select");
bSelect.addClickListener(buttonClickEvent -> {
if(selected.size() > 0)
{
dataList.clear();
dataList.addAll(selected);
selected.clear();
dataProvider.refreshAll();
}
});
hlTest.add(testGrid, bSelect);
With the given grid, click a few checkboxes and click 'Select'. The list is reduced to the selected rows, but the checkboxes are still ticked even though 'selected' is empty. The logging within 'rowSelected' is correctly returning the state.
If I remove the column and re-add to grid, then all is displayed correctly. Also, if I select all items in the grid then the select also works correctly.
Currently using Java17 and Vaadin 22.0.6 (have also tried 23.0.0 beta3).
Thanks.
I think you need to call dataProvider refresh when you update
lit.withFunction("handleCheckClick", (item) -> {
if(selected.contains(item))
selected.remove(item);
else
selected.add(item);
testGrid().getDataProvider().refreshAll();
});

How to get Selected Listbox Items using devexpress in winforms app?

I am trying to get selected item text. I used this below code
MessageBox.Show(listBoxColumnHeaders.SelectedItems);
Output
Devexpress.XtraEditors.BaseListboxControl+SelectedItemCollection
But my text is Country
Update
I add listbox items from another class. That class called FilterColumnHeader using below code
FilterControl fc = Application.OpenForms.OfType<FilterControl>().SingleOrDefault();
List<FilterColumnHeader> headers = new List<FilterColumnHeader>();
while (rd.Read())
{
headers.Add(new FilterColumnHeader { typeOfHeader = rd["type"].ToString(), columnHeadersName = rd["AsHeading"].ToString() });
}
fc.listBoxColumnHeaders.DisplayMember = "columnHeadersName";
fc.listBoxColumnHeaders.ValueMember = "typeOfHeader";
fc.listBoxColumnHeaders.DataSource = headers;
Now When I try to print using this below code,
MessageBox.Show(""+ listBoxColumnHeaders.SelectedItems[0].ToString());
It is showing in message box like below
`ProjectName.FilterColumnHeader`
The SelectedItems property returns a collection of selected objects. All you need to do is to cast the required object to your type:
var filterColumnHeader = (FilterColumnHeader)listBoxControl.SelectedItems[0];
I don't know if you found an answer but this works for me :
StringBuilder list = new StringBuilder();
foreach(var item in listBoxColumnHeaders.SelectedItems)
{
list.AppendLine(item as string);
}
MessageBox.Show(list.ToString());

Add custom message (not error) under under combobox/text field

I'm new to extjs and I'm looking for a way to add some custom message under my combobox field.
Depending on some conditions (eg. value selected) the message needs to have different text and/or style.
I could play with errorEl associated with my combobox and change it's message/style depending on the state, but this doesnt look like a good approach.
Are you aware of any plugin allowing to add such a message, or is there a shorter way to do this?
Thank you for your suggestions. I ended up writing my own plugin, which then I attached to combobox.
I added new element after error element and I changed messages based on proper combobox events.
afterCmpRender : function() {
var me = this, cmp = me.getCmp();
var messageWrapper = {
tag : 'div'
};
var messageEl = cmp.errorEl.insertSibling(messageWrapper, "after");
cmp.messageEl = messageEl;
Ext.Array.each(me.messages, function(message) {
var messageConfig = {
tag : 'div',
style : {
display : 'none'
}
};
var newElement = messageEl.insertSibling(messageConfig, "after");
newElement.setHTML(message.value);
newElement.addCls(message.classes);
me.registerMessageEvents(me, cmp, message, newElement);
});
}
I almost always use multiple elements for this, and would not make an attempt to change the field.
Depending on your context, which you didn't provide, I'd say you could have a look at:
Ext.form.field.Display
Ext.form.Label
Ext.tip.Tip
Ext.tip.QuickTip
I'd work with the class Ext.tip.Tip.
You can create
Ext.create('Ext.tip.Tip', {
id: 'myTip',
header: false
});
and then
var tip = Ext.getCmp('myTip');
tip.update('your custom tip message');
tip.showBy(comboboxComponent);
You could also use showAt(..) instead of showBy.
For more information look into the Docu
Here is a Fiddle link to an example.

AngularJS Kendo Treeview not updating

Thanks to the answer from "Words Like Jared" at Angularjs + kendo-ui treeview, I got my treeview working and everything was fine. Until - someone wanted to update/filter the treeview based on checkboxes and the like. My problem is that the tree does not update to reflect the change in the datasource made in the controller.
Based on the jsfiddle in the answer mentioned above, I have created one to show my problem.
http://jsfiddle.net/rajeshmathew/LwDs5/
if ($scope.showLimitedRecords) {
$scope.thingsOptions = {dataSource: $scope.things2}
} else {
$scope.thingsOptions = { dataSource: $scope.things1 };
}
Checking the checkbox does not affect the tree.
I am a newbie to AngularJS and angular-kendo, and I am wondering if this kind of an update is even supposed to work. I might be going at this the wrong way. Any help/suggestions are much appreciated.
Thanks!
You could create the data source explicitly and then set the data using its API:
$scope.thingsOptions = {
dataSource: new kendo.data.HierarchicalDataSource({
data: $scope.things1
})
}
$scope.toggleFlag = function () {
if ($scope.showLimitedRecords) {
$scope.thingsOptions.dataSource.data($scope.things2);
} else {
$scope.thingsOptions.dataSource.data($scope.things1);
}
}
(updated demo)

How can I set nested array values in meteor publish function?

I have two collection "contents" and "units". In the content collection is a field "unitID" which refers to the unit-collection. In the meteor publish function I want to add the unit type name of all new created contents:
Meteor.publish("contents", function () {
var self = this;
var handle = Contents.find().observe({
changed: function(contentdoc, contentid) {
var UnitName = Units.findOne({_id: contentdoc.unittypeid }, {fields: {type: 1}});
self.set("contents", contentid, {'content.0.typename': UnitName});
self.flush();
}
});
}
This works but it creates a new attribut "content.0.UnitName" instead of inserting the attribute "UnitName" in the first element of the content array:
[
{
_id:"50bba3ca8f3d1db27f000021",
'content.0.UnitName':
{
_id:"509ff643f3a6690c9ca5ee59",
type:"Drawer small"
},
content:
[
{
unitID:"509ff643f3a6690c9ca5ee59",
name: 'Content1'
}
]
}
]
What I want is the following:
[
{
_id:"50bba3ca8f3d1db27f000021",
content:
[
{
unitID:"509ff643f3a6690c9ca5ee59",
name: 'Content1',
UnitName:
{
_id:"509ff643f3a6690c9ca5ee59",
type:"Drawer small"
}
}
]
}
]
What am I doing wrong?
this.set within Meteor.publish only works on the top-level properties of an object, meaning it doesn't support Mongo-style dotted attributes. You'll have to call set with the entire new value of the contents array.
Caveat: What I am about to say is going to change in a future release of Meteor. We're currently overhauling the custom publisher API to make it easier to use, but in a way that breaks back-compatibility.
That said...
It looks like what you're trying to do is build a server-side join into the published collection "contents". Here, for reference, is the current code (as of 0.5.2) that publishes a cursor (for when your publisher returns a cursor object):
Cursor.prototype._publishCursor = function (sub) {
var self = this;
var collection = self._cursorDescription.collectionName;
var observeHandle = self._observeUnordered({
added: function (obj) {
sub.set(collection, obj._id, obj);
sub.flush();
},
changed: function (obj, oldObj) {
var set = {};
_.each(obj, function (v, k) {
if (!_.isEqual(v, oldObj[k]))
set[k] = v;
});
sub.set(collection, obj._id, set);
var deadKeys = _.difference(_.keys(oldObj), _.keys(obj));
sub.unset(collection, obj._id, deadKeys);
sub.flush();
},
removed: function (oldObj) {
sub.unset(collection, oldObj._id, _.keys(oldObj));
sub.flush();
}
});
// _observeUnordered only returns after the initial added callbacks have run.
// mark subscription as completed.
sub.complete();
sub.flush();
// register stop callback (expects lambda w/ no args).
sub.onStop(function () {observeHandle.stop();});
};
To build a custom publisher that is joined with another table, modify the added callback to:
check if the added object has the key you want to join by
do a find in the other collection for that key
call set on your subscription with the new key and value you want to be published, before you call flush.
Note that the above is only sufficient if you know the key you want will always be in the other table, and that it never changes. If it might change, you'll have to set up an observe on the second table too, and re-set the key on the sub in the changed method there.

Resources