Jquery UI autocomplete with value label pairs - jquery-ui

I would like to set the source of autocomplete to the one that can have value/label pairs as described in their documentation here
http://api.jqueryui.com/autocomplete/
They say that
An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]
The label property is displayed in the suggestion menu. The value will
be inserted into the input element when a user selects an item. If
just one property is specified, it will be used for both, e.g., if you
provide only value properties, the value will also be used as the
label.
In my code I have
html
<input type="text" id="testBox" name="testBox" maxlength="70"/>
in my js
var catsArr = [];
for (var i = 0; i < 10; i++) {
var cat = {
label: "grey " + i,
value: i
};
catsArr.push(cat);
}
//tie the autocomplete to the box
$("#testBox").autocomplete({ source: catsArr });
But somehow, when the user starts typing the word grey, nothing shows up....What am I missing?

Related

How to get input box (filterbox) values from ui-grid column header

I'm trying to get the input box values present in the ui-grid column header.
I'm trying to use my own filtering function which requires to get values from multiple input boxes in the column header.
$scope.gridOptions.columnDefs = [
{
field: 'name',
displayName: 'Name',
headerCellTemplate: '<input type='text' disallow-spaces placeholder='Enter to Search' ng-model='testCol' id='Enter to Search'>},
];
You can give your custom filter to the columnDef like this:
$scope.gridOptions.columnDefs = [
{
field: 'name',
displayName: 'Name',
headerCellTemplate: '<input type='text' disallow-spaces placeholder='Enter to Search' ng-model='testCol' id='Enter to Search'>,
filter: {
type: uiGridConstants.filter.INPUT,
condition: myCustomFilterFunction
},
];
and your filtering function will look something like this:
function myCustomFilterFunction(term, value, row, column){
//do something here
}
uiGrid will call the myCustomFilterFunction everytime the filter input changes. The parameter term refers is what you were looking for. It's the value present in the input box. Parameter value refers to the value of the column for the current row. Parameters row and col give you access to the current rowEntity and column.
myCustomFilterFunction should return a boolen. If the returned value for a row is true then the row is displayed otherwise not.

Free Text Entry in Angular Material mdAutoComplete

I want my angular material autocomplete to be a list of suggestions but not requirements. However I'm not sure how to implement as their is no clear example from the Angular Material docs.
In the example below my model is $ctrl.item.category
Clearly the example below is wrong, as my model is linked to md-selected-item, but this only works if I select an item. I want the user to be able to free enter the text if the item is not in the list. Basically how autocomplete already works in most browsers.
I see plenty of questions on how to disable this, but they are not trying to disable so much as clean up the left over text when an item is not selected. In these cases when an item is not selected then the model value is null, but text is left in the input.
I want the text left int he input to be the model value if the person does not select (or a match is not made).
md-autocomplete(
md-floating-label="Category Name"
flex="50"
md-input-name="category"
md-selected-item="$ctrl.item.category"
md-search-text="catSearch"
md-items="category in $ctrl.categories"
md-item-text="category"
md-min-length="0"
md-select-on-match=""
md-match-case-insensitive=""
required=""
)
md-item-template
span(md-highlight-text="catSearch" md-highlight-flags="^i") {{category}}
My options ($ctrl.categories) is an array of strings ['Food','Liqour'] and I wan the user to be able to use one of those or free enter Tables as their choice.
In this case you should link md-search-text to your model.
If you want to implement fuzzy search you have to write the filter method yourself. Look at this example:
template:
<md-autocomplete
md-items="item in $ctrl.itemsFilter()"
md-item-text="item.label"
md-search-text="$ctrl.query"
md-selected-item="$ctrl.selected"
>
<md-item-template>
<span md-highlight-text="$ctrl.query">{{item.label}}</span>
</md-item-template>
<md-not-found>
No item matching "{{$ctrl.query}}" were found.
</md-not-found>
<div ng-messages="$ctrl.myValidator($ctrl.query)">
<div ng-message="short">Min 2 characters</div>
<div ng-message="required">Required value</div>
</div>
</md-autocomplete>
controller:
var items = [ ... ];
ctrl.itemsFilter = function itemsFilter() {
return ctrl.query ? filterMyItems(ctrl.query) : items;
};
ctrl.myValidator = function (value) {
return {
short: value && value.length < 2,
required : value && value.length < 1,
};
};
then you just need to add filterMyItems method to filter your items
To improve the answer of #masitko, I have implemented the filter in a way, that it adds the query to the filtered list. So it becomes selectable and a valid option. So it's possible to make the autocomplete a suggestion box.
I'm using ES6 in my projects. But it should be easily adaptable to ES5 code.
myFilter() {
if (!this.query) return this.items;
const
query = this.query.toLowerCase(),
// filter items where the query is a substing
filtered = this.items.filter(item => {
if (!item) return false;
return item.toLowerCase().includes(query);
});
// add search query to filtered list, to make it selectable
// (only if no exact match).
if (filtered.length !== 1 || filtered[0].toLowerCase() !== query) {
filtered.push(this.query);
}
return filtered;
}

array observable with content observable and jqAutocomplete

I'm using Knockout 3 with the plugin jqAutocomplete by Ryan Niemeyer. I have a problem with this model:
var ViewModel = function() {
var self = this;
self.myOptionsObs = ko.observableArray([
{ id: ko.observable(1), name: ko.observable("item 1 o"), description: ko.observable("item label 1 o") },
{ id: ko.observable(2), name: ko.observable("item 2 o"), description: ko.observable("item label 2 o") },
{ id: ko.observable(3), name: ko.observable("item 3 o"), description: ko.observable("item label 3 o") }
]);
self.myValueObs = ko.observable();
};
ko.applyBindings(new ViewModel());
<input data-bind="jqAuto: { source: myOptionsObs, value: myValueObs, inputProp: 'name', template: 'itemTmpl' }" />
As you can see, there is an observable array and each element is also an observable.
The autocomplete don't work well. As you can see in this Fiddle, the left column has an observable array but its elements aren't observable. If you click in the left box and write something, a list of options appear.
But in the right column, you have the same, but the element's are all observable. If you click in the right box and write something, when the list appear, if you move the cursor up and down, you could see that the row 'name' gets deleted and filled with zeros.
What I have to change in my data-bind attribute?
This question is related with this question.
I have to say that this solution works ok for me. But the updated plugin don't.
Thanks !!
The jqAutoComplete plugin isn't setup to work with observable properties (although it could be enhanced to do so without much work).
For now, I think that your best bet is to create a computed that will always return a plain and up-to-date version of your options.
self.myOptionsObs.plain = ko.computed(function() {
return ko.toJS(self.myOptionsObs);
});
Sample: http://jsfiddle.net/rniemeyer/45cepL9b/
I'll try to take a look at some point about supporting observable properties. Shouldn't take many changes.

jqTreeView - getting selected node's value in select event

Following is how I populate my jqTreeView.
View
#Html.Trirand().JQTreeView(
new JQTreeView
{
DataUrl = Url.Action("RenderTree"),
Height = Unit.Pixel(500),
Width = Unit.Pixel(150),
HoverOnMouseOver = false,
MultipleSelect = false,
ClientSideEvents = new TreeViewClientSideEvents()
{
Select="spawnTabAction"
}
},
"treeview"
)
<script>
function spawnTabAction(args, event) {
alert(args);
}
</script>
Controller
public JsonResult RenderTree()
{
var tree = new JQTreeView();
List<JQTreeNode> nodes = new List<JQTreeNode>();
nodes.Add(new LeafNode { Text = "Products", Value="Product/Product/Index" });
FolderNode fNode = new FolderNode { Text = "Customers" };
fNode.Nodes.Add(new LeafNode() { Text = "Today's Customers", Value = "Customer/Customer/Today" });
nodes.Add(fNode);
nodes.Add(new LeafNode { Text = "Suppliers", Value = "Supplier/Supplier/Index" });
nodes.Add(new LeafNode { Text = "Employees", Value = "Employee/Employee/Index" });
nodes.Add(new LeafNode { Text = "Orders", Value = "Order/Order/Index" });
return tree.DataBind(nodes);
}
What I want to do is spawn a tab based on the Value of the selected node. I tried a lot but couldn't get hold of the selected node's value.
Later I checked the DOM of rendered page and found that the value is nowhere added to the node but magically when I select the node the value appears in a hidden control by the name treeview_selectedState (treeview being the id of the control). I even traced all ajax calls but couldn't find anything.
Questions:
1) Where does it keep the Values of tree nodes?
2) How do I get the Selected Node's value in select event?
I even tried to get the treeview_selectedState control's value in select event but it returned [].
Then I added a button the view and hooked that onto a js function and found the value there. It makes me think that the value is not available in select event, am I right in thinking that?
I don't think getting selected node's value should be a this big deal? Am I missing something very obvious?
Thanks,
A
After trying so many things , I checked their demo and found the hints there (I shouldve done this as the first thing).
It was actually pretty straight forward
function spawnTabAction(args, event) {
alert($("#treeview").getTreeViewInstance().getNodeOptions(args).value);
}
Thanks,
A

extjs4 grid - changing column editor per row basis

ExtJS4 grid anticipates appropriate editor (cellEditor or rowEditor) per column.
If a column's header field is dateField - date selector will be applied on every row in that column.
What I need is an editor with different field editors per row, not per column.
The Extjs3 solution is provided here - unfortunately doesn't fit in Extjs4 case.
(please check that link to see explanatory images, cause I can't post images yet)
There's also a single column solution called property grid, but again - it supports only one column and is very deviated from the standard Ext.grid component
I have tried manually changing grid editor by customizing column.field and reloading grid.editingPlugin.editor, but always get a blank rowEditor panel with no fields.
//by default rowEditor applies textField to all cells - I'm trying to force custom numberFiled on apropriate row
var numberField=Ext.form.field.Number();
grid.columns[0].field=numberField;
//destroy current rowEditor's instance
delete grid.editingPlugin.editor;
//now, upon doubleClick on apropriate cell it should reinitialize itself (initEditor()) - and it does, but is an empty panel
what am I missing here? once I delete editingPlugin.editor everything should start from the beginning like during the first time rowEditor is called, but it looses all the fields
Solution for Ext4:
I was looking for a solution for this and this guy said the property grid has this behavior.
I have adapted it to work in a clean way for me
on initComponent I declared:
this.editors = {
'date' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date', {selectOnFocus: true})}),
'string' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text', {selectOnFocus: true})}),
'number' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
'int' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
editable: false,
store: [[ true, 'Sim' ], [false, 'Não' ]]
})})
};
I used these functions to help me (copied):
this.renderCell = function(val, meta, rec) {
var result = val;
if (Ext.isDate(val)) {
result = me.renderDate(val);
} else if (Ext.isBoolean(val)) {
result = me.renderBool(val);
}
return Ext.util.Format.htmlEncode(result);
};
this.getCellEditor = function(record, column) {
return this.editors[record.get('type')];
};
And finally, associate these functions to the column:
{text: "Valor", name : 'colunaValor', width: 75, sortable: true, dataIndex: 'valor', width:200,
renderer: Ext.Function.bind(this.renderCell, this),
getEditor: Ext.Function.bind(this.getCellEditor, this)
}

Resources