change tabulator's placeholder at runtime - tabulator

I bumped into the problem of how to change tabulator's placeholder at runtime. As it is suggested to ask questions on StackOverflow, here it is. There is an issue (closed - https://github.com/olifolkerd/tabulator/issues/1415) having a suggested solution that I tried. Unfortunately, it throws an error during creation:
tabulator.min.js:4 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at s.redraw (tabulator.min.js:4)
at e.h.redraw (tabulator.min.js:6)
at ResizeObserver.<anonymous> (tabulator.min.js:12)
tabulator version is 4.9.3. jsfiddle: https://jsfiddle.net/ivos/6pq75brv/3/
the setup is simple:
var data = [{id:1}, {id:2}, {id:3}];
var placeholder = $("<span>Waiting for data</span>");
var conf = {
// placeholder: "Waiting for data",
placeholder: placeholder,
columns: [
{ title: "Id", field: "id", headerFilter: "input" },
],
dataFiltered: (filters, rows) =>{
placeholder.text(filters.length > 0 ? 'No Results': 'Waiting for data');
},
};
var t = new Tabulator('#tbl', conf);
setTimeout(function(){ t.setData(data)}, 5000); // timeout is just to show the initial placeholder
If I apply a filter (i.e. 5) I got
Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at s.redraw (tabulator.min.js:4)
at e.h.redraw (tabulator.min.js:6)
at ResizeObserver.<anonymous> (tabulator.min.js:12)

Because Tabulator uses a virtual DOM you cannot manipulate elements from outside of it.
There is no built in way to change the place holder option once the table has been set.
That being said i can certainly point you to a very hacky way of achieving this, that i would recommend against because it manipulates internal variables and that may result in it not working in future, but it should achieve what you are hoping for.
So assuming you are creating your table on a variable called table, the following should work:
table.options.placeholder = "new placeholder message";

Related

Jest Expected and receive are identical

Is there a reason why Jest would see this as a not identical when both seem exactly the same?
So here is the code I am using to do the test, it's basically just a function that calls for an event emiter, in the event emiter if the date is invalid, I let it as is :
const datepickerComponent: Datepicker = new Datepicker();
const mockEvent = {
target: {
classList: {
remove: jest.fn(),
add: jest.fn(),
},
value: '01-01-197',
},
} as unknown as InputEvent;
datepickerComponent.onInput(mockEvent);
const emitMock: jest.Mock = jest.fn();
datepickerComponent.dsdDatepickerInputChange = { emit: emitMock } as unknown as EventEmitter<dsdDatepickerInputChangeEvent>;
// when
datepickerComponent.onInput(mockEvent);
const dateValue = new Date('197-01-01T00:00:00');
// then
expect(emitMock).toHaveBeenCalledWith({ value: '197-01-01', valueAsDate: dateValue });
The reason why you are observing this error is because whilst Date { NaN } values look the same, they actually refer to different object instances and cannot be traversed for equality any further, hence the actual error should be the following:
Expected: {"value": "197-01-01", "valueAsDate": Date { NaN }}
Received: serializes to the same string
(To reproduce this error - create two new dates using new Date('197-01-01T00:00:00') and pass them into .equals())
To get past this error, all you need to do is to simply refactor your .toHaveBeenCalledWith test into the following:
const calledWithArg = emitMock.mock.calls[0][0];
expect(JSON.stringify(calledWithArg)).toEqual(JSON.stringify({ value: '197-01-01', valueAsDate: dateValue }));
The reason why .toHaveBeenCalledWith does not work is because it does not allow us to reshape the argument object before a comparison (in our case we need to stringify it), hence we can alternatively extract the argument that the mock was called with via .mock.calls[0][0], stringify it and then compare it to the stringified version of the expected object.
Reference of valueAsDate is different. But Jest doc affirm it uses .toEqual for comparison. That means it try to deeply compare two new Date. This is a bad idea, you don't control the Date class, and there are probably some moving parts inside.
To loose match a value, you can check this issue: https://stackoverflow.com/a/55569458/7696155

Ambiguos "Error: NEXUS__UNKNOWN__TYPE was already defined and imported as a type" error in nexus graphql

I'm getting the following error when using nexus to define a graphql schema with apollo-server.
Error: NEXUS__UNKNOWN__TYPE was already defined and imported as a type
The stacktrace doesn't give much information as to where the issue is occurring or to what the problem is. The project has 20+ models and dozens of resolvers so it's quite hard to debug.
Error: NEXUS__UNKNOWN__TYPE was already defined and imported as a type, check the docs for extending types
at extendError (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1744:2)
at SchemaBuilder.addType (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:603:8)
at SchemaBuilder.missingType (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1212:5)
at SchemaBuilder.getOrBuildType (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1540:4)
at SchemaBuilder.getOutputType (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1471:10)
at SchemaBuilder.buildOutputField (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1349:52)
at /Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1307:7
at Array.forEach (<anonymous>)
at SchemaBuilder.buildOutputFields (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1306:7)
at fields (/Users/username/Documents/folder/folder/graphq-nexus-prisma-api/node_modules/nexus/src/builder.ts:1009:33)
Any help appreciated.
I got the same error, but it was because I removed some exports. I'm not exactly sure what caused it, but I basically have a file that exports all of my graphql modules. E.g.
// graphql/modules/index.ts
export * from './file-a';
export * from './file-b';
When I removed the second export line, I started getting the error. I'm probably using some of the types defined in file-b somewhere else, and that's somehow causing the error. Anyway, adding the line back in fixed it (I had removed it by accident anyway).
UPDATE
I also go this by referencing some arg types that didn't exist (typo). For example:
args: {
where: arg({ type: 'ConversationsWhereInput' }),
orderBy: arg({ type: 'ConversationsOrderByInput', list: true }),
},
The s in Conversations shouldn't be there. It should be:
args: {
where: arg({ type: 'ConversationWhereInput' }),
orderBy: arg({ type: 'ConversationOrderByInput', list: true }),
},
It could have been much helpful if you could elaborate what did you do before this error happened.
I just came up with this error exactly as same as what you got and for me it was because I just accidentally changed the name for objectType of typeDef.
For instance, the name for the FollowUserResult was actually FollowResult and after I changed the name, the whole mutation resolvers related to this objectType became wrong.
export const FollowUserResult = objectType({
name: "FollowUserResult", // It was originally "FollowResult"
definition(t) {
t.nonNull.boolean("ok");
t.string("error");
},
});
You may check on this again. Once you got those correct, delete the schema.graphql file and generate the new schema.graphql file.
I got this error because I was using the incorrect Node version. My project didn't have a .nvrmc file (yet) so I was using Node 10 on a project that uses Node 14. So after switching to the correct Node version this error went away
I got this error when I incorrectly specified an unknown type in the type attribute of an extension to the Query type. More specifically:
export const CoursesQuery = extendType({
type: "Query",
definition(t) {
t.field("myQuery", {
type: InvalidType, // <--- Changing InvalidType to the correct type fixed the error
async resolve(_parent, _args, ctx) {
return ...
},
});
},
});
The error disappeared after I changed InvalidType to the correct type and restarted the server.

How to force nodejs script argument to take value from choices list using commander?

I am using commander in node.js script. I am able to set default value to one argument.
var args = require('commander')
// set 'pending' as defaut value of status
args.option('-s --status <statusString>', 'Status to filter questions', 'pending').parse(process.argv)
console.log('status:', args.status)
How can I force status value to be from ["pending", "rejected", "accepted", "hold"] only? I did not find anything relevant in documention.
This is what I could achieve:
var options = ["pending", "rejected", "accepted", "hold"];
args.option(
'-s --status <statusString>',
`Status to filter questions: ${options}`,
function(val, _) {
if (!options.includes(val)) {
throw Error(`${val} is not from ${options}`);
}
return val;
},
'pending')
.parse(process.argv)
Not perfect, since you need to format help string and validate input value by yourself. Also, throwing an error from the validation function is not handled by Commander nicely and causes it to fail with the whole stacktrace in the output. I could not find a better way to tell Commander that the input is invalid.
In my case I finally just switched to argparse, which is a clone of the Python command line parser, and seems to be better thought over. This is how you limit choices with it:
const ArgumentParser = require('argparse').ArgumentParser;
const argparser = new ArgumentParser({ description: 'An example'});
argparser.addArgument('--status', {
choices: ['pending', 'rejected', 'accepted', 'hold'],
defaultValue: 'pending'});
const args = argparser.parseArgs();
This will do the job, including nice help message and input validation.
I think that in your case this is what you were looking for:
args
.addOption(
new Option('-s --status <statusString>', 'Status to filter questions')
.choices(["pending", "rejected", "accepted", "hold"])
.default('pending')
)
.parse(process.argv)
Also please take a look to another specific example I've prepared and tested successfully (NPM commander v8.2.0)
program
.addOption(
new Option('-s --status <statusString>', 'Status to filter questions')
.choices(["pending", "rejected", "accepted", "hold"])
.default('pending')
)
.action((args) => {
console.log(args)
})
Side note: please notice that for this second example I've used a slightly different naming convention for clarity: I've used program (vs original args) in the first line, as I was planning to use args name for the variable array received in the arrow function used in action() instead. Don't let that change confuse you! ;)
IMPORTANT: more on the official examples, direct link to a related example right here: https://github.com/tj/commander.js/blob/HEAD/examples/options-extra.js#L13

Firebase Cloud Function - Reference.update failed

I'm getting the following error when invoking a GCF:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
Done a bit of digging online but can't find the same issue. Without adding way too much info, I'm trying to add dish objects into a category object in Realtime Database. The odd thing is, the function works fine for the first 6 dishes, and when I try to add a 7th, this error pops up and the update method fails.
The full error log, with my unique property data is:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
'users.sIRf7m1uWfa9j0iF6UuuzvdD5TG2.dishcategories.default01.dishes.u3o1p278vriqo3odeslle.categories.0.dishes.irdrl2q7blsi1y7ih3jhh.categories.0.dishes.v8pl7r9llhfp7sqmz7uikk.categories.0.dishes.2ee3ajy6d5vymneewgflze.categories.0.dishes.btdib119nz5cnm6zk5uu4t.categories.0.dishes.4wyu5yqyn2z0bgvcejix9.categories.0.dishes.w1cfcpktym7nkp76p521n.categories.0.createdDate'
at ValidationPath.checkValid_ (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1035:19)
at ValidationPath.push (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1015:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1478:18
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
Here's the cloud function code from index.ts:
// Now we need to check if this dish's categories already exist as user categories.
// If they do, we can add this newly created dish into them.
// If they don't, we can create them with this newly added dish in them.
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish) // *** This is the update method producing the error in this case ***
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish)
}
})
Anyone know what this error means, and perhaps what I'm doing wrong here? Thanks!
The error message is quite explicit: you're trying to write data that is more than 32 levels deep, or which contains a cyclic object.
Given the code you shared, the latter seems most likely: you're looping over each category of a dish, and then write that dish to each category again. The simplest fix I can think of is to write the dish-without-categories to each category:
dish_without_categories = dish;
delete dish_without_categories.categories;
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
})

Fabric: error loading subclass object from JSON

In this jsfiddle I have a line that is created from a subclass (it's basically a line with two additional attributes). I'm trying to serialize/deserialize the line to/from JSON. I can serialize with no problems (including the two additional attributes) but when I try to deserialize with loadFromJSON I get the Cannot read property 'async' of undefined exception.
Uncomment the last line in the jsfiddle to get the error.
I implemented the fromObject() method, but I'm not sure it's correct. What's wrong with this code?
Javascript:
var canvas = new fabric.Canvas('c');
fabric.PolySegment = fabric.util.createClass(fabric.Line, {
type: 'seg',
initialize: function(points,options) {
options || (options = { });
this.callSuper('initialize', points,options);
this.set('poly', options.poly);
this.set('id', options.id);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
poly: this.get('poly'),
id: this.get('id')
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
}
});
fabric.PolySegment.fromObject = function (object, callback) {
return new fabric.PolySegment(object);
};
fabric.PolySegment.async = true;
var coords1 = [ 10, 10, 100, 100 ];
var seg1 = new fabric.PolySegment(coords1, {
stroke: 'black',
strokeWidth: 6,
originX: 'left',
originY: 'top',
poly: 111111,
id: 222222
});
canvas.add(seg1);
var json = JSON.stringify(canvas);
document.getElementById('t').innerHTML = json;
// uncomment the line below, you'll get an exception
//canvas.loadFromJSON(json);
In looking at your Fiddle, it seems like the issue is the type value you have given your new class. If I change:
type: 'seg',
to
type: 'polySegment',
and uncomment the last line, I don't get the error. However, I also don't get the line to load on the canvas. But I guess I'm not 100% sure what is happening in your script there - you're loading the polySegment, then converting it to JSON and reloading it? I'm assuming this is merely for illustration purposes.
While what I suggest here gets rid of your error, I'm personally not 100% sure why it works. In reading the FabricJS documentation on Subclassing, it doesn't specify that the subclass type needs to match that of the subclass definition, but it seems to work...
I hope that helps in some way.
One last comment about this, I've always used the toJSON method to transfer a canvas element to JSON. Though this retrieves a JSON object, not a string like you are doing. Also, the toJSON method requires that you specify what properties you want to capture, so maybe this isn't the best method for your case. It's discussed on this page. But my point for bringing this up, is I know for certain that the toJSON method works well with the loadFromJSON method. So I mention that in case you find the JSON.stringify method to be the issue, there is a alternate method to approach the same concept.

Resources