Extjs 6.0 - ItemSelector: how to programmatically focus/highlight an element? - extjs

I have a ItemSelector component inside a Window. I have implemented a search functionality that dynamically finds the matching entry based on user's keyboard input.
Now I just want to highlight/focus such item inside the ItemSelector.
I'm looking for something like:
// when the search returned a result and got the related index in the store
function onSearchPerformed(index) {
var cmp = this;
cmp.itemSelector.setSelected(index); // here I'd be highlighting the entry
}
Example
Imagine a simple ItemSelector like this one taken from the web.
User types 'Delaw' and my search function detects that there is an entry with name Delaware and it's at position 3 in the store.
All I want to do is to programmatically highlight the row/entry 'Delaware' just as if you clicked on it.

This ux component uses a boundList, or better 2 of them.
A from and a toList.
You need to get a reference to the right boundlist.
More on that you will find here: http://docs.sencha.com/extjs/6.0.1/classic/src/ItemSelector.js.html
Basically you can do something like this:
https://fiddle.sencha.com/#view/editor&fiddle/24ec
afterrender: function(cmp){
Ext.defer(function(){
var boundlist = cmp.down('boundlist');
item = boundlist.all.item(1);
boundlist.highlightItem(item);
},300);
}
After you have a ref to the correct boundlist, you can simply highlight the item using:
http://docs.sencha.com/extjs/6.0.1/classic/Ext.view.BoundList.html#method-highlightItem
Take care that you may need to call following function before:
http://docs.sencha.com/extjs/6.0.1/classic/Ext.view.BoundList.html#method-clearHighlight
To find the correct item should't be too hard.

There are two ways to solve the issue
One is by following #devbnz answer, marked as correct. This is preferable, if you just want to graphically highlight the entry without triggering any event.
However, by hovering on other entries, you will lose the highlight on your current entry.
The second one, as suggested by #guilherme-lopes in the comments, may be preferable in cases in which you want the selection to act as if you actually clicked on an entry, which will trigger the selectionchange event and similar...
Depending on the situation, I ended up using either.

Related

how can I add an item in specific position

I have two forms which are extended from another form. I want to add some fields to one of them but not at the bottom of the form. I use add method and my items are added at the bottom of the form.
Does anyone have an idea?
You need to use insert method on container instead of container.add to update the layout.
The insert takes two args,
first : index to insert at
second: the element to be inserted (could by a couple of other things)
In your case the form serves as the container so you need to do something like (assuming you are on Ext 5.x or lower):
var newField = Ext.create('Ext.form.field.Field', {});
var insertAt = 3;
yourForm.insert(insertAt, newField);
Take a look at the fiddle as well: https://fiddle.sencha.com/#view/editor&fiddle/2e0i
Edit: Removed the hacky way

ngAnimate to detect changes from $http-call with interval

I have an array with a few items in it. Every x seconds, I receive a new array with the latest data. I check if the data has changed, and if it has, I replace the old one with the new one:
if (currentList != responseFromHttpCall) {
currentList = responseFromHttpCall;
}
This messes up the classes provided by ng-animate, as it acts like I replaced all of the items -- well, I do actually, but I don't know how to not.
These changes can occur in the list:
There's one (or more) new item(s) in the list - not necessaryly at the end of the list though.
One (or more) items in the list might be gone (deleted).
One (or more) items might be changed.
Two (or more) items might have been swapped.
Can anyone help me in getting ng-animate to understand what classes to show? I made a small "illustation" of my problem, found here: http://plnkr.co/edit/TS401ra58dgJS18ydsG1?p=preview
Thanks a lot!
To achieve what you want, you will need to modify existing list on controller (vm.list) on every action. I have one solution that may work for your particular example.
you would need to compare 2 lists (loop through first) similar to:
vm.list.forEach((val, index)=>{
// some code to check against array that's coming from ajax call
});
in case of adding you would need to loop against other list (in your case newList):
newList.forEach((val, index)=>{
// some code to check array on controller
});
I'm not saying this is the best solution but it works and will work in your case. Keep in mind - to properly test you will need to click reset after each action since you are looking at same global original list which will persist same data throughout the app cycle since we don't change it - if you want to change it just add before end of each function:
original = angular.copy(vm.list);
You could also make this more generic and put everything on one function, but for example, here's plnkr:
http://plnkr.co/edit/sr5CHji6DbiiknlgFdNm?p=preview
Hope it helps.

Expand specific rows in Angular-ui-grid

I'm using angular-ui-grid 3.0.5 with the treeview extension to display a tree. The data loads normally, everything works as expected, except that expandRow fails silently.
My use case is this: suppose we have a path like a > b > c and I need c shown to the user as preselected. I know the selection is correctly done because when I manually expand the parent rows, the child row is indeed selected.
Should I call expandAllRows, all rows would be expanded. However, calling expandRow with references on rows a and b taken from gridOptions.data leads to nothing happening: all rows will remain collapsed.
Is there any precaution to be taken that I have maybe overlooked, or is this a bug?
There's one mention in a closed issue that may be related to this but problem I'm having, but I'm not even sure it's related, given how dry the comment/solution was.
There's no example of using expandRow in the documentation but it's in both the API and the source code.
The gridRow objects mentioned in the documentation http://ui-grid.info/docs/#/api/ui.grid.treeBase.api:PublicApi are not the elements you put into the data array (though this seems to be not explained anywhere).
What the function expects is an object that the grid creates when building the tree, you can access them by looping through the grids treeBase.tree array. This will only be valid when the grid has built the tree, it seems, so it is not directly available when filling in the data, that's why registering a DataChangeCallback helps here https://github.com/angular-ui/ui-grid/issues/3051
// expand the top-level rows
// https://github.com/angular-ui/ui-grid/issues/3051
ctrl.gridApi.grid.registerDataChangeCallback(function() {
if (ctrl.gridApi.grid.treeBase.tree instanceof Array) {
angular.forEach(ctrl.gridApi.grid.treeBase.tree, function(node) {
if (node.row.treeLevel == 0) {
ctrl.gridApi.treeBase.expandRow(node.row);
}
});
}
});
self.onContentReady = function (e) {
e.component.expandRow(e.component.getKeyByRowIndex(0));
e.component.expandRow(e.component.getKeyByRowIndex(1));
};
selec which row you wanna expand

Assign instance id when the wpf app has multiple controls on page identified as one instance

Is it possible to use searchProperties.Add("Instance","1"); to assign instance id where the wpf application has multiple controls like buttons or combo boxes which are recognized as one instance of the control. If yes then how to do this? Any code sample is appreciated.
An addendum to AdrianHHH's excellent suggestion is to iterate through the FindMatchingControls collection and figure out which one is the one you want. If it's always collection[3] then you can identify it and act on it as such.
Your code would look like this:
var button = new WinButton(winWindowChild(mainParentCtName, childParentCtName));
//if you pass parents when you construct an object it can speed up find
button.SearchProperties.Add(/*any identifying properties*/);
var allButtons = button.FindMatchingControls();
//test code
foreach (var btn in allButtons)
Mouse.Click(btn); //watch this to figure out what order the buttons are iterating through, then remove loop
Mouse.Click(allButtons[3]);
Mouse.DoubleClick(allButtons[0]);
Mouse.Hover(allButtons[1]);

Winforms datagrid default values

This drives me crazy:
i'm using a datagridview (bound to a dataset) and textboxes also bound to the dataset (which means that everything typed into the textboxes is reflected in the datagridview). The datagridview is actually used only to show up the values (user is NOT able to edit anything in the cells).
So: when the user pushes the add new record button (automatically created by visual studio using binding navigator etc. ) i would like to programmatically select this new line (remember: user has not the ability to select with the mouse) and insert some values.
I tried to use the
DefaultValuesNeeded
event, but this is firing only if the user selects the row with the asterisk indicator (what the user is not allowed to do).
How can i simulate that behavior? Should i take another approach?
Thanks in advance!!
Was searching for alternatives to how I currently do this and just wanted to let you know about a couple ways I know of. Both of these will set defaults when using the * (new row) or using a BindingNavigator.
private void CityBindingSource_AddingNew(object sender,
AddingNewEventArgs e)
{
// Simply set the default value to the next viable ID,
// will automatically set the value when needed.
locationDataSet.CITY.CITY_IDColumn.DefaultValue =
CityTableAdapter.GetNewID(); // ++maxID;
}
Or
private void CityDataGridView_DefaultValuesNeeded(object sender,
DataGridViewRowEventArgs e)
{
// Gets called when datagridview's */NewRow is entered.
e.Row.Cells[0].Value = CityTableAdapter.GetNewID(); // ++maxID;
}
private void bindingNavigatorAddNewItem_Click(object sender,
EventArgs e)
{
// BindingNavigator button's AddNewItem automatic tie-
// in to bindingSource's AddNew() is removed.
// This sets the current cell to the NewRow's cell to trigger
// DefaultValuesNeeded event.
CityDataGridView.CurrentCell =
CityDataGridView.Rows[CityDataGridView.NewRowIndex].Cells[1];
}
I was really hoping to use this:
private void CityBindingSource_AddingNew(object sender,
AddingNewEventArgs e)
{
// Cast your strongly-typed
// bindingsource List to a DataView and add a new DataRowView
DataRowView rowView =
 ((DataView)CityBindingSource.List).AddNew();
var newRow = (LocationDTSDataSet.CITYRow)rowView.Row;
newRow.CITY_ID = CityTableAdapter.GetNewID();
newRow.CMMT_TXT = "Whatever defaults I want";
e.NewObject = rowView;
}
But when adding using the BindingNavigator or any code based bindingSource.AddNew() it results in just a blank row. Hopefully someone finds a better way, but this is working for me so far.
Revised:
How about the Datatable's TableNewRow event, then? If that gets fired when the BindingNavigator creates a new row, then that's an opportunity to populate the object.

Resources