Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] fix(Column): minResizeWidth #535

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions addon/classes/Column.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { A as emberArray, makeArray } from '@ember/array';
import { warn } from '@ember/debug';
import EmberObject, { computed } from '@ember/object';
import { isEmpty } from '@ember/utils';
import { guidFor } from '@ember/object/internals';
import { isEmpty, typeOf } from '@ember/utils';
import fixProto from 'ember-light-table/utils/fix-proto';

/**
Expand Down Expand Up @@ -129,11 +130,37 @@ export default class Column extends EmberObject.extend({

/**
* The minimum width (in px) that this column can be resized to.
* @property minResizeWidth
* @property _minResizeWidth
* @type {Number}
* @default 0
* @private
*/
_minResizeWidth: 0,

/**
* The minimum width that this column can be resized to.
* @property minResizeWidth
* @type {String}
* @default '0px'
*/
minResizeWidth: 0,
minResizeWidth: computed({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing dependent key _minResizeWidth.

In practice this won't cause any problems yet, since _minResizeWidth is private API and exclusively managed by the minResizeWidth computed property. However, that could possibly change in the future and the developer making that change then might not remember to add that key.

get() {
return this.get('_minResizeWidth');
},
set(key, value) {
if (typeOf(value) === 'string') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeof value === 'string'

is a bit faster. The only advantage of typeOf(item) is that it correctly detects String object instances as string, i.e. typeOf(new String('foo')) === 'string'.

Personally idc a lot about this scenario, but that just might be because this has never bitten me yet. Keep this line whatever you feel the most comfortable with. 😉

let [, quantity, units] = value.match(/(\d+)(px)?/) || [];
if (units !== 'px') {
warn('`value` attribute is interpreted as px regardless of provided units', {
id: 'ember-light-table.classes.Column'
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const [, quantity, units] = value.match(/^\s*(\d+)([a-z]+|%)?\s*$/) || [];
assert(
  `'minResizeWidth' can only interpret px unit values. You passed '${quantity}${unit}'.`,
  isEmpty(units) || units === 'px'
);

Being more restrictive here can help prevent subtle bugs. We should throw an assertion here, since 1rem would be interpreted as 1px in the original code, which does not make sense.

}
this.set('_minResizeWidth', Number(quantity));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return this.set('_minResizeWidth', Number(quantity));

I wrote a unit test for the work, but I am unsatisfied with it because I had to do col.get('_minResizeWidth') and not col.get('minResizeWidth') because the latter was returning undefined. Any idea why that could be?

This is why. When using the computed({ get(k) { ... }, set(k , v) { ... } }) form, the setter method needs to return a value as well, as per the API docs:

The set function should accept two parameters, key and value. The value returned from set will be the new value of the property.

By prepending return to this.set(k, v) you return the value passed to it, since this.set(k, v) returns v.

} else {
this.set('_minResizeWidth', value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return this.set('_minResizeWidth', value);

Also, what about other non-string values? What if I pass NaN, {}, false, null, ...? I think we should handle these cases a bit more explicitly and maybe even throw assertions / TypeErrors for some scenarios.

Copy link
Author

@balos1 balos1 Jan 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@buschtoens The only concern I have about throwing assertions for TypeErrors is that it could cause people who are incorrectly using minResizeWidth currently to start receiving an exception when they did not before, and depending on how well they handle errors in their app, this could cause them problems. Now you can argue that since they are already using it incorrectly, this is actually better, but it is something to think about.

I plan on making the suggested changes this upcoming week.

}
}
}),

/**
* The parent column (or group) for this sub-column.
Expand Down
26 changes: 25 additions & 1 deletion tests/unit/classes/column-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,31 @@ test('CP - visibleSubColumns', function(assert) {
assert.equal(col.get('visibleSubColumns.length'), 0);
});

test('CP - minResizeWidth', function(assert) {
let col = new Column({
minResizeWidth: '100px'
});
assert.ok(col);
assert.equal(col.get('_minResizeWidth'), 100);
col = new Column({
minResizeWidth: '100%'
});
assert.ok(col);
assert.equal(col.get('_minResizeWidth'), 100);

col = new Column({
minResizeWidth: '100'
});
assert.ok(col);
assert.equal(col.get('_minResizeWidth'), 100);

col = new Column({
minResizeWidth: 100
});
assert.ok(col);
assert.equal(col.get('_minResizeWidth'), 100);
});

test('subColumns / parent', function(assert) {
let col = new Column({
subColumns: [{}]
Expand All @@ -86,5 +111,4 @@ test('subColumns / parent', function(assert) {
assert.equal(col.subColumns.length, 1);

assert.equal(col.subColumns[0].get('parent'), col);

});