canEdit not working in dgrid while loading by default - dojo

I have a tree grid with following ui requirements on edit.
Cost column for certain rows are editable.
Editable rows should be available for edit by default always and not
based on any event.
Each row has min max range. As and when the user enters a value that
needs to be validated.
Here is the column structure I have defined for dgrid.
var columns = [
tree({label: "Name", field:"name" }),
{ label : "Description", field:"description" },
editor({label: "Cost", field: "cost", canEdit : function(rowItem){ return rowItem.isEditable;}}, dijit.form.NumberTextBox),
{label:"Min - Max Range", field:"minRange", get:getMinMax, id:'minMax'}
];
Though the tree and edit is working fine, I have few issues to be resolved.
When editOn is not provided for editor, the column is made editable
by default. However, canEdit is getting invoked only when we provide
spl event in editOn parameter. Is there a way to get canEdit invoked
even during default load.
I need to set a range constraint for NumberTextBox dynamically for
each row. Is there an easy way to set the constraint based on row
value.
Thank you very much for your help

As for canEdit invoked when editOn is false check:
https://github.com/SitePen/dgrid/issues/623
As for dynamic set value based on row values you can try :
on the widget level Extend the Widget : in
startup after inherited(arguments)
var _row=this.grid.grid.row(this.domNode.parentNode);
this.query={myParam:_row.data.maxRange};
Tsemach.

Related

api side validateUniqueness for multiple field in RedwoodJS

According to rw docs we can check uniqueness of fields before starting process like this
validateUniqueness('user', { filed: value }, (db)=>{})
But how can we validate multiple field at same time.
Note: below wont operate correctly
validateUniqueness('user', { filed1: value, filed2: value }, (db)=>{})

Error trying to reorder items within another list in Keystone 6

I'm using KeystoneJS v6. I'm trying to enable functionality which allow me to reorder the placement of images when used in another list. Currently i'm setting up the image list below, however I'm unable to set the defaultIsOrderable to true due to the error pasted.
KeystoneJS list:
Image: list({
fields: {
title: text({
validation: { isRequired: true },
isIndexed: 'unique',
isFilterable: true,
isOrderable: true,
}),
images: cloudinaryImage({
cloudinary: {
cloudName: process.env.CLOUDINARY_CLOUD_NAME,
apiKey: process.env.CLOUDINARY_API_KEY,
apiSecret: process.env.CLOUDINARY_API_SECRET,
folder: process.env.CLOUDINARY_API_FOLDER,
},
}),
},
defaultIsOrderable: true
}),
Error message:
The expected type comes from property 'defaultIsOrderable' which is declared here on type 'ListConfig<BaseListTypeInfo, BaseFields<BaseListTypeInfo>>'
Peeking at the definition of the field shows
defaultIsOrderable?: false | ((args: FilterOrderArgs<ListTypeInfo>) => MaybePromise<boolean>);
Looking at the schema API docs, the defaultIsOrderable lets you set:
[...] the default value to use for isOrderable for fields on this list.
You're trying to set this to true but, according to the relevant section of the field docs, the isOrderable field option already defaults to true.
I believe this is why the defaultIsOrderable type doesn't allow you to supply the true literal – doing so would be redundant.
So that explains the specific error your getting but I think you also may have misunderstood the purpose of the orderBy option.
The OrderBy Option
The field docs mention the two effects the field OrderBy option has:
If true (default), the GraphQL API and Admin UI will support ordering by this field.
Take, for example, your Image list above.
As the title field is "orderable", it is included in the list's orderBy GraphQL type (ImageOrderByInput).
When querying the list, you can order the results by the values in this field, like this:
query {
images (orderBy: [{ title: desc }]) {
id
title
images { publicUrl }
}
}
The GraphQL API docs have some details on this.
You can also use the field to order items when listing them in the Admin UI, either by clicking the column heading or selecting the field from the "sort" dropdown:
Note though, these features order items at runtime, by the values stored in orderable fields.
They don't allow an admin to "re-order" items in the Admin UI (unless you did so by changing the image titles in this case).
Specifying an Order
If you want to set the order of items within a list you'd need to store separate values in, for example, a displayOrder field like this:
Image: list({
fields: {
title: text({
validation: { isRequired: true },
isIndexed: 'unique',
isFilterable: true,
}),
displayOrder: integer(),
// ...
},
}),
Unfortunately Keystone doesn't yet give you a great way to manage this the Admin UI (ie. you can't "drag and drop" in the list view or anything like that). You need to edit each item individually to set the displayOrder values.
Ordering Within a Relationship
I notice your question says you're trying to "reorder the placement of images when used in another list" (emphasis mine).
In this case you're talking about relationships, which changes the problem somewhat. Some approaches are..
If the relationship is one-to-many, you can use the displayOrder: integer() solution shown above but the UX is worse again. You're still setting the order values against each item but not in the context of the relationship. However, querying based on these order values and setting them via the GraphQL API should be fairly straight forward.
If the relationship is many-to-many, it's similar but you can't store the "displayOrder" value in the Image list as any one image may be linked to multiple other items. You need to store the order info "with" the relationship itself. It's not trivial but my recent answer on storing additional values on a many-to-many relationship may point you in the right direction.
A third option is to not use the relationship field at all but to link items using the inline relationships functionality of the document field. This is a bit different to work with - easier to manage from the Admin UI but less powerful in GraphQL as you can't traverse the relationship as easily. However it does give you a way to manage a small, ordered set of related items in a many-to-many relationship.
You can save an ordered set of ids to a json field. This is similar to using a document field but a more manual.
Hopefully that clears up what's possible with the current "orderBy" functionality and relationship options. Which of these solutions is most appropriate depends heavily on the specifics of your project and use case.
Note too, there are plans to extend Keystone's functionality for sorting and reordering lists from both the DX and UX perspectives.
See "Sortable lists" on the Keystone roadmap.

Selecting rows from DataTables fails unless search UI is visible

I want to hide the search user interface, but when I do so, the api based row selection fails. Works fine if searching is enabled. When I read the docs, I thought I was disabling the UI, but it is obviously the search feature instead.
I actually have DataTables for schools and school districts, and want to only display the schools from a specific district when used clicks on district table to select a district. User can also select a school from the school table
// DataTable Initialization for school table
dTable = $tblSchools.DataTable({
select: {
style: 'single',
items: 'row',
},
paging: false,
searching: true, // selecting rows only works when enabled - makes sense
info: false,
destroy: true
});
// snippet from event handler on 'select' event of district table
var dTable = $tblSchools.DataTable();
var district = '123'; // real code messier, console.log(district) shows it works
// district number is always column 1
// the next line is what fails (silently, no exception)
dTable.column(1).search(district, false, false).draw();
Environment, jQuery 1.9.1, DataTables 1.10.12, select plugin 1.2.0
Is there some setting I have overlooked to hide the search UI without disabling the search function entirely.
If I have to do this a different way, would appreciated being pointed to a simple equivalent way that allows me to hide the DataTables search UI, but show schools based on district.
Is there some setting I have overlooked to hide the search UI without
disabling the search function entirely
Yes. Remove the f flag from the dom defaults :
dTable = $tblSchools.DataTable({
dom: 'lrtip',
...
})
Now the filter input / "search UI" is removed but you can still perform searches by code.

Can I retrieve column/search specific data from a jQuery DataTable?

I am currently working on a page for a web app that displays member data in a jQuery DataTable. I am building a custom plugin for the DataTable that allows for a wide range of filtering per table column.
My current task is to be able to retrieve filtered data from the DataTable, although not updating that data on the table. I know already it is possible to retrieve all filtered data by doing:
var data = $table.dataTable().$('tr', { filter: 'applied' });
This gets data for any text in the search box and any filters applied to columns. I am also aware this call gets the jQuery selectors of cells. That's what I need. But I need more...
My questions are:
Can I get data by only applying what's in the search box, without any other current filters applied to columns? I tried:
var data = $table.dataTable().$('tr', { search: 'applied' });
But that returns the same as { filter : 'applied' }.
Can I target specific columns for getting data, such as:
var data = $table.dataTable().$('tr', { filter: 'applied', columns: [1, 2, 5] });
Can I target specific columns AND what's in the search box?
My plugin needs to able to keep track of data with various combinations of column/search filters applied.
For DataTables 1.9
There is a fnFilter() API method but it applies filtering to the table which is not what you want.
Alternatively you may want to use fnGetData() to get the data for the whole table and filter it yourself.
For DataTables 1.10
There is a search() API method but it applies filtering to the table when used with draw() which is not what you want.
Also there is filter() API method. It is not exactly what you're looking for but very close, however you would need to perform the searching yourself.
You can retrieve the content of the search box as follows:
var searchVal = $('.dataTables_filter input', $table).val();
Then you would need to do the searching yourself, shown below is a simplistic approach which may not match how DataTables perform the search internally.
To search first and second column only, specify [0,1] to columns() method. If no parameters are specified, all columns will be searched instead.
var filteredData = $table.DataTable()
.columns([0, 1])
.data()
.eq( 0 )
.filter( function ( value, index ) {
returrn (value.search(new RegExp(searchVal, "i")) !== -1)
? true : false;
} );
According to the manual, variable filteredData would contain a new API instance with the values from the result set which passed the test in the callback.
To retrieve data for all or selected columns, use columns().data().

searchAttr combobox array

I was wondering how could I have mutli-search Attr in my combobox. I would like to have someting like :
var cb = dijit.byId('myCombo');
cb.attr('store', store);
cb.attr('searchAttr', ["name","age"]);
So I can make autocomplete on two criterias.
I will assume you are using a dojo.data.ItemFileReadStore. The searchAttr is only for the attribute you're typing in the ComboBox.
For example, if you're typing a name, but you also want to filter by age, you add a field to the query parameter:
// Get names with age=30
// Use set because attr is deprecated
cb.set( 'query', { 'age' : 30 });
If you want to be more specific with a name when the page is initially loaded, you can specify it in your query:
// All names starting with 'a' and age=30
cb.set( 'query', { 'name' : 'a*', 'age' : 30 });
If you want your age to be dynamic, you must get it from another place (e.g. dijit, form element, dom node, etc.). Here is an example to get age from another dijit called 'anotherDijit' (a NumberTextBox for example) when the page loads:
// Get names with age specified in 'anotherDijit'
cb.set( 'query', { 'age' : dijit.byId('anotherDijit').getValue() } );
However, for the age value in the query to change when the 'anotherDijit' diijt changes, you have to do one of two things:
Attach an observer/event handler to an appropriate 'anotherDijit' event (e.g. onChange), which will update the new 'anotherDijit' value in your ComboBox store query. This is a PUSH approach.
Attach an observer/event handler to an appropriate ComboBox event (e.g. onFocus), which will PULL the current value from the 'anotherDijit' dijit, and then update the store query parameter.
Notice that the fields you put in 'query' parameter are queried like AND (name=this AND age=that, etc). If you need more complex queries, with ORs and NOTs, you can use dojox.data.AndOrReadStore, for example.