What is the best way to add selectable space on a tabulator row that only has columns that grap the single click for edting? - tabulator

I have a very simple table that is set up like this.
{
"tabulator": {
"rowSelected": "function(row){ this.send({topic:this.config.topic,ui_control:{'callback':'rowSelected','row':row.getData(), 'position':row.getPosition()}}); }",
"rowAdded": "function(row){ this.send({topic:this.config.topic,ui_control:{'callback':'rowAdded','row':row.getData(), 'position':row.getPosition()}}); }",
"rowDeleted": "function(row){ this.send({topic:this.config.topic,ui_control:{'callback':'rowDeleted','row':row.getData(), 'position':row.getPosition()}}); }",
"rowMoved": "function(row){ this.send({topic:this.config.topic,ui_control:{'callback':'rowMoved','row':row.getData(), 'position':row.getPosition()}}); }",
"rowUpdated": "function(row){ this.send({topic:this.config.topic,ui_control:{'callback':'rowUpdated','row':row.getData(), 'position':row.getPosition()}}); }",
"dataLoaded": "function(data) {var newData=[];data.forEach(function (datum) {var command = [datum.id, datum.torque, datum.duration];newData.push(command);});this.send({topic:this.config.topic,ui_control:{callback:'dataLoaded',data: newData}});}",
"dataEdited": "function(data) {var newData=[];data.forEach(function (datum) {var command = [datum.id, datum.torque, datum.duration];newData.push(command);});this.send({topic:this.config.topic,ui_control:{callback:'dataEdited',data: newData}});}",
"layout": "fitColumns",
"selectable": true,
"columns": [{
"field": "id",
"visible": false
}, {
"title": "Torque",
"field": "torque",
"editor": "number",
"editorParams": {
"step": 0.1
}
}, {
"title": "Duration",
"field": "duration",
"editor": "number"
}]
},
"customHeight": 12
}
I want to be able to select a row or rows with the standard click mechanism. However the rows only contain fields that have a numeric editor. The editor grabs all the single clicks on the row. I have implemented a really bad way of overcoming by introducing a column that has a title set to "Click me" and nothing else. This looks terrible. Does anyone has any suggestions on how I this can be done? I want to avoid using the the rowSelection formatter.
Thanks,
Roger

yes, in the Event, there is a target (or Source ... I forget). I use it on my custom headerFilters that have dropdowns, to distinguish between the user interacting with my dropdown, and Tabulator thinking the user has clicked in the header to move the column or change the sortOrder. If the target/source is my dropdown, I stopPropagation. If not, I let it through. In your case, you prolly want to stopPropagation if they are interacting with your editor.

Related

Power Automate FIlter Array with Array Object as Attribute

i have a Object-Array1 with some Attributes that are Object-Array2. I want to filter my Object-Array1 only to these elements, that contain a special value in Object-Array2. How wo i do this? Example:
{
"value": [
{
"title": "aaa",
"ID": 1,
"Responsible": [
{
"EMail": "abc#def.de",
"Id": 1756,
},
{
"EMail: "xyz#xyz.com",
"Id": 289,
}
]
},
{
"title": "bbbb",
"ID": 2,
"Responsible": [
{
"EMail": "tzu#iop.de",
"Id": 1756,
}
]
}
]
}
I want to filter my Object-Array1 (with title & id) only to these elements, that contain abc#def.de
How do i do this in Power Automate with the "Filter Array" Object? I tried this way, but didn't work:
Firstly, you haven't entered an expression, you've entered text. That will never work.
Secondly, even if you did set that as an expression, I don't think you'll be able to make it work over an array, at least, not without specifying more properties and making it a little more complex.
I think the easiest way is to use a contains statement after turning the item into a string ...
The expression I am using on the left hand side is ...
string(item()?['Responsible'])
... and this is the result ...

Tabulator - rowContextMenu - HowTo get which cell the mouse-rightclick is performed

Is it possible to get which cell the right-click context menu is performed with rowContextMenu?
rowContextMenu gives the data for all cells in the row, but I have not found how to get which cell the action happens.
Using contextMenu could be an option, but I want to build the columns-setup serverside as json and load the columns with
table.setColumns(columnsJson)
Setting columns contextmenu as a function is not a valid json,
columns": [
{ "title": "", "field": "age", "sorter": "string", "headerSort": false, "contextMenu": cellContextMenu}
]
And setting the "contextMenu" as a "string" fails with: error: "Uncaught TypeError: o.forEach is not a function"
columns": [
{ "title": "", "field": "age", "sorter": "string", "headerSort": false, "contextMenu": "cellContextMenu"}
]
Any tips on getting which cell the menu is trigged with rowContextMenu?
Or is there maybe a different/better solution builtin in Tabulator?
Reason for building the column setup serverside is that I want to have different context menu based on type of cell-data, and it will vary based on selection by user.
BR
Bjorn
If you want to get the cell that is being clicked on then you need to use the Cell Context Menu instead as this is passed the cell component that has been clicked.
You would then need to assign the menu per cell but this is easy if you define it as an array outside the table and then reference it on each column definition using the contextMenu property:
//define cell context menu
var cellContextMenu = [
{
label:"Reset Value",
action:function(e, cell){
cell.setValue("");
}
},
]
//add header menu in column definition
var table = new Tabulator("#example-table", {
columns:[
{title:"Name", field:"name",contextMenu:cellContextMenu},
{title:"Age", field:"age",contextMenu:cellContextMenu},
{title:"Address", field:"address",contextMenu:cellContextMenu},
]
});

Azure Search match against two properties of the same object

I would like to do a query matches against two properties of the same item in a sub-collection.
Example:
[
{
"name": "Person 1",
"contacts": [
{ "type": "email", "value": "person.1#xpto.org" },
{ "type": "phone", "value": "555-12345" },
]
}
]
I would like to be able to search by emails than contain xpto.org but,
doing something like the following doesn't work:
search.ismatchscoring('email','contacts/type,','full','all') and search.ismatchscoring('/.*xpto.org/','contacts/value,','full','all')
instead, it will consider the condition in the context of the main object and objects like the following will also match:
[
{
"name": "Person 1",
"contacts": [
{ "type": "email", "value": "555-12345" },
{ "type": "phone", "value": "person.1#xpto.org" },
]
}
]
Is there any way around this without having an additional field that concatenates type and value?
Just saw the official doc. At this moment, there's no support for correlated search:
This happens because each clause applies to all values of its field in
the entire document, so there's no concept of a "current sub-document
https://learn.microsoft.com/en-us/azure/search/search-howto-complex-data-types
and https://learn.microsoft.com/en-us/azure/search/search-query-understand-collection-filters
The solution I've implemented was creating different collections per contact type.
This way I'm able to search directly in, lets say, the email collection without the need for correlated search. It might not be the solution for all cases but it works well in this case.

No results when in the mapping, the field _all has specified an index_analyzer

With Elasticsearch I have created an index using a custom mapping and custom set of analszers, however I'm not able to do query search on the _all field.
I'm using these analyzers:
{
"analysis": {
"analyzer": {
"case_insensitive": {
"type": "custom",
"tokenizer": "keyword",
"filter": [
"lowercase",
"asciifolding"
],
"char_filter": "punctuation"
}
},
"char_filter": {
"punctuation": {
"type": "mapping",
"mappings": [
".=>\\u0020",
"-=>\\u0020",
"_=>\\u0020"
]
}
}
}
}
and this mapping:
{
"article": {
"_all": {
"enabled": true,
"store": "yes",
"index_analyzer": "case_insensitive",
"search_analyzer": "case_insensitive"
},
"properties": {
"title": {
"type": "string",
"index": "analyzed"
},
"subtitle": {
"type": "string",
"analyzer": "case_insensitive"
},
"comment": {
"type": "string",
"index": "not_analyzed"
},
"review": {
"type":"string",
"index": "not_analyzed",
"include_in_all":false
}
}
}
}
Then I add a document like this:
{
"title": "This is the story of a wonderful man.",
"subtitle":"A man goes on vacation in the worst place possible.",
"comment": "I like the movie very much, however I did not undertand it.",
"review":"Very well"
}
and I expect the following 3 out of 4 fields shall be included in _all, in particular title, subtitle and comment.
The analyzer is working as following (tested using the analyzer test in elasticsearch):
"I like the movie very much, however I did not undertand it." -> "i like the movie very much, however i did not undertand it "
"This is the story of a wonderful man." -> "this is the story of a wonderful man "
I expect that at least searching on _all using the query: "This is the story of a wonderful man." I should be able to find the document.
What am I doing wrong?
How is elasticsearch populating the _all field?
If the field 'title' shall be added to the _all field, which data is used and how? is it using the output of the analyzer selected for the 'title' field as input for the analyzer of the _all or is using the raw data?
How is the flow of data in the _all field? For example
input -> analyzer -> title -> index_analyser -> _all
or
input -> analyzer -> title
-> index_analyser -> _all
Thank you in advance...
Your mapping looks ok to me. The only thing I would try is to set one of the fields explicitly to include_in_all=true and then rerun your query.
According to the docs, it may be that as you are overriding the default value of include_in_all for one of the fields, it may have changed it for all the other fields of the objects. See here _all
Relevant text from the documentation is below:
Inclusion in the _all field can be controlled on a field-by-field basis by using the include_in_all setting, which defaults to true. Setting include_in_all on an object (or on the root object) changes the default for all fields within that object.
UPDATE:
I think I know why its not working. Here is what I did. First, I removed the custom analysers from the _all_ field (so using the standard analyser). With this I was able to query and get the results as expected. Results were returned for terms that were in any of the document attributes but review. At least this confirms that the general behaviour of _all is correct. Next to test the analysers, I did a query on the subtitle field with the exact text(as it is using keyword analyser). This also worked. Then I realised that _all is an aggregated field and then analysed.
So the query should include all the text from all the fields to work. But again, how do we know in which order they were aggregated :)
This link _all custom analyser has some information. Relevant bits extracted below (from Shay).
You don't want to set the analyzer for _all to be keyword, _all is an aggregation of all the other fields int the doc, so you basically treat the whole aggregation of text as a single token.

How to search through data with arbitrary amount of fields?

I have the web-form builder for science events. The event moderator creates registration form with arbitrary amount of boolean, integer, enum and text fields.
Created form is used for:
register a new member to event;
search through registered members.
What is the best search tool for second task (to search memebers of event)? Is ElasticSearch well for this task?
I wrote a post about how to index arbitrary data into Elasticsearch and then to search it by specific fields and values. All this, without blowing up your index mapping.
The post is here: http://smnh.me/indexing-and-searching-arbitrary-json-data-using-elasticsearch/
In short, you will need to do the following steps to get what you want:
Create a special index described in the post.
Flatten the data you want to index using the flattenData function:
https://gist.github.com/smnh/30f96028511e1440b7b02ea559858af4.
Create a document with the original and flattened data and index it into Elasticsearch:
{
"data": { ... },
"flatData": [ ... ]
}
Optional: use Elasticsearch aggregations to find which fields and types have been indexed.
Execute queries on the flatData object to find what you need.
Example
Basing on your original question, let's assume that the first event moderator created a form with following fields to register members for the science event:
name string
age long
sex long - 0 for male, 1 for female
In addition to this data, the related event probably has some sort of id, let's call it eventId. So the final document could look like this:
{
"eventId": "2T73ZT1R463DJNWE36IA8FEN",
"name": "Bob",
"age": 22,
"sex": 0
}
Now, before we index this document, we will flatten it using the flattenData function:
flattenData(document);
This will produce the following array:
[
{
"key": "eventId",
"type": "string",
"key_type": "eventId.string",
"value_string": "2T73ZT1R463DJNWE36IA8FEN"
},
{
"key": "name",
"type": "string",
"key_type": "name.string",
"value_string": "Bob"
},
{
"key": "age",
"type": "long",
"key_type": "age.long",
"value_long": 22
},
{
"key": "sex",
"type": "long",
"key_type": "sex.long",
"value_long": 0
}
]
Then we will wrap this data in a document as I've showed before and index it.
Then, the second event moderator, creates another form having a new field, field with same name and type, and also a field with same name but with different type:
name string
city string
sex string - "male" or "female"
This event moderator decided that instead of having 0 and 1 for male and female, his form will allow choosing between two strings - "male" and "female".
Let's try to flatten the data submitted by this form:
flattenData({
"eventId": "F1BU9GGK5IX3ZWOLGCE3I5ML",
"name": "Alice",
"city": "New York",
"sex": "female"
});
This will produce the following data:
[
{
"key": "eventId",
"type": "string",
"key_type": "eventId.string",
"value_string": "F1BU9GGK5IX3ZWOLGCE3I5ML"
},
{
"key": "name",
"type": "string",
"key_type": "name.string",
"value_string": "Alice"
},
{
"key": "city",
"type": "string",
"key_type": "city.string",
"value_string": "New York"
},
{
"key": "sex",
"type": "string",
"key_type": "sex.string",
"value_string": "female"
}
]
Then, after wrapping the flattened data in a document and indexing it into Elasticsearch we can execute complicated queries.
For example, to find members named "Bob" registered for the event with ID 2T73ZT1R463DJNWE36IA8FEN we can execute the following query:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "flatData",
"query": {
"bool": {
"must": [
{"term": {"flatData.key": "eventId"}},
{"match": {"flatData.value_string.keyword": "2T73ZT1R463DJNWE36IA8FEN"}}
]
}
}
}
},
{
"nested": {
"path": "flatData",
"query": {
"bool": {
"must": [
{"term": {"flatData.key": "name"}},
{"match": {"flatData.value_string": "bob"}}
]
}
}
}
}
]
}
}
}
ElasticSearch automatically detects the field content in order to index it correctly, even if the mapping hasn't been defined previously. So, yes : ElasticSearch suits well these cases.
However, you may want to fine tune this behavior, or maybe the default mapping applied by ElasticSearch doesn't correspond to what you need : in this case, take a look at the default mapping or, for even further control, the dynamic templates feature.
If you let your end users decide the keys you store things in, you'll have an ever-growing mapping and cluster state, which is problematic.
This case and a suggested solution is covered in this article on common problems with Elasticsearch.
Essentially, you want to have everything that can possibly be user-defined as a value. Using nested documents, you can have a key-field and differently mapped value fields to achieve pretty much the same.

Resources