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

feat(sort): add ability to manage and display sorting #5307

Merged
merged 22 commits into from Jun 27, 2017

Conversation

andrewseguin
Copy link
Contributor

@andrewseguin andrewseguin commented Jun 22, 2017

Introduces the MdSort which contains MdSortable elements. The MdSort manages the active sort and direction while each MdSortable element changes and displays the sorting for its field.

MdSortHeader is the first MdSortable to be introduced, to be easily used within CdkTable.

h3kcxzdxbq3

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Jun 22, 2017
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

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

Got some strict null errors


/** Overrides the reverse order value of the containing MdSort for this MdSortable. */
@Input()
get reverseOrder() { return this._reverseOrder; }
Copy link
Member

Choose a reason for hiding this comment

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

I don't follow what this does

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For setting the sort order as

descending -> ascending -> [none] -> descending -> ...

as opposed to

ascending -> descending' -> [none] -> descending -> ...

Copy link
Member

Choose a reason for hiding this comment

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

Isn't that what start already does?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not quite - start determines where in the cycle the user is placed when first clicked. reverseOrder will reverse the cycle.

Sounds like I misunderstood your intentions on start, which would reverse the order.

We could remove one or the other and we'd lose a minor and probably unnecessary cycle. I prefer keeping reverseOrder over start though

Copy link
Member

@jelbourn jelbourn Jun 23, 2017

Choose a reason for hiding this comment

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

Yeah, my intent was that:
Default: asc -> desc -> none
Start = desc: desc -> asc -> none

Copy link
Member

@jelbourn jelbourn Jun 23, 2017

Choose a reason for hiding this comment

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

I think having both of these is more confusing than helpful. The problem with "reverse" is that you have to know what the default is. Saying start or startWith, in my mind, better captures the developer's intent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SGTM - removed the reverse. Agreed that just start is enough

@@ -0,0 +1,20 @@
<div class="mat-sort-header-container"
[class.mat-sort-header-position-before]="arrowPosition == 'before'">
<button class="mat-sort-header-button"
Copy link
Member

Choose a reason for hiding this comment

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

Add type="button"

host: {
'(click)': '_sort.sort(this)',
'[class.mat-sort-header-sorted]': '_isSorted()',
}
Copy link
Member

Choose a reason for hiding this comment

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

Add ViewEncapsulation.None and ChangeDetectionStrategy.OnPush

}

.mat-sort-header-stem {
background: black;
Copy link
Member

Choose a reason for hiding this comment

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

Color should be part of the theme (or maybe just currentColor?)

this.id = this._cdkColumnDef.name;
}

this._sort.register(this);
Copy link
Member

Choose a reason for hiding this comment

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

Should be able to do this in the constructor

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cannot do this since the MdSort creates a mapping of id to MdSortable and this is the earlier lifecycle hook where we have the id available


constructor(@Optional() public _sort: MdSort,
public _intl: MdSortIntl,
@Optional() public _cdkColumnDef: CdkColumnDef) {
Copy link
Member

Choose a reason for hiding this comment

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

Put the @Optional args next to each other?


/** Whether this MdSortHeader is currently sorted in either ascending or descending order. */
_isSorted() {
return this._sort.active == this.id && this._sort.direction != '';
Copy link
Member

Choose a reason for hiding this comment

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

Just this._sort.active == this.id && this._sort.direction?

/**
* Register function to be used by the contained MdSortables. Adds the MdSortable to the
* collection of MdSortables.
* @docs-private
Copy link
Member

Choose a reason for hiding this comment

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

Why @docs-private here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm I wasn't thinking others needed it but people implementing their own MdSortable certainly would. Removed

@@ -0,0 +1,20 @@
<div class="mat-sort-header-container" type="button"
[class.mat-sort-header-position-before]="arrowPosition == 'before'">
<button class="mat-sort-header-button"
Copy link
Member

Choose a reason for hiding this comment

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

Still needs type="button"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah misunderstood, thought this was an accessibility thing, putting type on the wrong element. Good now

host: {
'(click)': '_sort.sort(this)',
'[class.mat-sort-header-sorted]': '_isSorted()',
},
Copy link
Member

Choose a reason for hiding this comment

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

Still missing view encapsulation none and onpush

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, got removed in testing. It's back in

@andrewseguin
Copy link
Contributor Author

Good for another review round

* found in the LICENSE file at https://angular.io/license
*/

export type SortDirection = 'ascending' | 'descending' | '';
Copy link
Member

Choose a reason for hiding this comment

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

Maybe just asc and desc?

if (!sortable) { return ''; }

// Get the sort direction cycle with the potential sortable overrides.
const disableClear = sortable.disableClear != undefined ?
Copy link
Member

Choose a reason for hiding this comment

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

Prefer doing == null or != null (it captures both null and undefined and is shorter)

throw getMdSortHeaderNotContainedWithinMdSortError();
}

_sort.mdSortChange.subscribe(() => _changeDetectorRef.markForCheck());
Copy link
Member

Choose a reason for hiding this comment

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

Need to unsubscribe to this on destroy

}

ngOnDestroy() {
this._sort.unregister(this);
Copy link
Member

Choose a reason for hiding this comment

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

nit: deregister

],
}).compileComponents();

fixture = TestBed.createComponent(SimpleMdSortApp);
Copy link
Member

Choose a reason for hiding this comment

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

createComponent has to go in a separate beforeEach block because compileComponents() is asynchronous

@andrewseguin
Copy link
Contributor Author

Made the changes, thanks

let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
let valueB = isNaN(+propertyB) ? propertyB : +propertyB;

return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'ascending' ? 1 : -1);
Copy link
Member

Choose a reason for hiding this comment

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

Missed a spot

<cdk-cell *cdkCellDef="let row"> {{row.id}} </cdk-cell>
</ng-container>

<!-- Column Definition: Progress -->
<ng-container cdkColumnDef="progress">
<cdk-header-cell *cdkHeaderCellDef> Progress </cdk-header-cell>
<cdk-header-cell *cdkHeaderCellDef
md-sort-header start="descending">
Copy link
Member

Choose a reason for hiding this comment

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

Here too

@andrewseguin
Copy link
Contributor Author

D'oh, forgot to export my last fixes - should be good to go

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

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

LGTM

@jelbourn jelbourn added merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note pr: lgtm action: merge The PR is ready for merge by the caretaker and removed pr: needs review labels Jun 26, 2017
@jelbourn
Copy link
Member

Caretaker note: this will need a new build rule

Copy link

@ErinCoughlan ErinCoughlan left a comment

Choose a reason for hiding this comment

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

LGTM


/** A label to describe the current sort (visible only to screenreaders). */
sortDescriptionLabel = (id: string, direction: SortDirection) => {
return `Sorted by ${id} ${direction}`;

Choose a reason for hiding this comment

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

If direction is 'asc' | 'desc', won't that sound strange with a screenreader? I wonder if you want to override it to be a real word, but I'm not super familiar with what the standards are here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, I'll add a check for this

@tinayuangao tinayuangao merged commit b328d36 into angular:master Jun 27, 2017
amcdnl pushed a commit to amcdnl/material2 that referenced this pull request Jul 8, 2017
* feat(sort): add sortable

* checkin

* checkin

* feat(sort): add sort header

* overrides, tests

* format demo html

* add ngif to screenready label

* add new line to scss

* fix tests

* fix types

* fix types

* shorten coerce import

* comments

* comments

* rebase

* specialize intl to header; make public

* remove reverse

* button type and onpush

* rename sort directions (shorten)

* small changes

* remove consolelog

* screenreader
@andrewseguin andrewseguin deleted the sortable branch November 28, 2017 20:36
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants