diff --git a/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.spec.ts b/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.spec.ts index 2b1bf17b7b2b..2be12ff748d0 100644 --- a/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.spec.ts +++ b/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.spec.ts @@ -134,4 +134,27 @@ describe('slider template migrator', () => { `, ); }); + + it('should remap input & output event handlers', async () => { + await runMigrationTest( + ` + `, + ` + `, + ); + await runMigrationTest( + ` + `, + ` + `, + ); + await runMigrationTest( + ` + `, + ` + `, + ); + }); }); diff --git a/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.ts b/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.ts index a5e831998f81..47ac87af2beb 100644 --- a/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.ts +++ b/src/material/schematics/ng-generate/mdc-migration/rules/components/slider/slider-template.ts @@ -42,6 +42,8 @@ export class SliderTemplateMigrator extends TemplateMigrator { const inputBindings: string[] = []; const comments: string[] = []; + let alreadyAppendedTemplateVars = false; + for (let i = 0; i < bindings.length; i++) { const binding = bindings[i]; @@ -71,7 +73,29 @@ export class SliderTemplateMigrator extends TemplateMigrator { updates.push(this._removeBinding(originalHtml, binding.node)); } - // TODO(wagnermaciel): Finish the remapping of other bindings. + if (binding.name === 'input' || binding.name === 'change') { + // Replace $event with a MatSliderChange object. + const sourceSpan = binding.node.sourceSpan; + const oldBindingStr = originalHtml.slice( + sourceSpan.start.offset, + sourceSpan.end.offset, + ); + const newBindingStr = oldBindingStr.replace( + '$event', + '{source: ngSliderThumb, parent: ngSlider, value: ngSliderThumb.value}', + ); + + // Remove the old binding and add the new binding to the . + inputBindings.push(newBindingStr); + updates.push(this._removeBinding(originalHtml, binding.node)); + + if (!alreadyAppendedTemplateVars) { + // Add the necessary template vars used in the MatSliderChange object. + inputBindings.push('#ngSliderThumb="matSliderThumb"'); + updates.push(this._insertTemplateVar(node, 'ngSlider')); + alreadyAppendedTemplateVars = true; + } + } } if (comments.length) { @@ -94,7 +118,18 @@ export class SliderTemplateMigrator extends TemplateMigrator { return updates; } - /** Returns an update the adds the given comments before the given template ast element. */ + /** Returns an update that inserts a template var at the end of the given node. */ + private _insertTemplateVar(node: compiler.TmplAstElement, varName: string): Update { + return { + offset: node.startSourceSpan.end.offset - 1, + updateFn: html => + html.slice(0, node.startSourceSpan.end.offset - 1) + // -1 to stop before the closing '>' + ` #${varName}` + + html.slice(node.startSourceSpan.end.offset - 1), + }; + } + + /** Returns an update that adds the given comments before the given template ast element. */ private _addComments(node: compiler.TmplAstElement, comments: string[]): Update { const whitespace = this._parseIndentation(node); const indentation = '\n' + this._parseIndentation(node); diff --git a/src/material/slider/public-api.ts b/src/material/slider/public-api.ts index 61a5f5406168..6c81c26c059d 100644 --- a/src/material/slider/public-api.ts +++ b/src/material/slider/public-api.ts @@ -9,5 +9,5 @@ export {MatSlider} from './slider'; export {MatSliderVisualThumb} from './slider-thumb'; export {MatSliderThumb, MatSliderRangeThumb} from './slider-input'; -export {MatSliderDragEvent} from './slider-interface'; +export {MatSliderDragEvent, MatSliderChange} from './slider-interface'; export {MatSliderModule} from './module'; diff --git a/src/material/slider/slider-interface.ts b/src/material/slider/slider-interface.ts index 54ec955f86de..de2a191d463e 100644 --- a/src/material/slider/slider-interface.ts +++ b/src/material/slider/slider-interface.ts @@ -65,6 +65,22 @@ export interface MatSliderDragEvent { value: number; } +/** + * A simple change event emitted by the MatSlider component. + * @deprecated Use event bindings directly on the MatSliderThumbs for `change` and `input` events. See https://material.angular.io/guide/mdc-migration for information about migrating. + * @breaking-change 17.0.0 + */ +export class MatSliderChange { + /** The MatSliderThumb that was interacted with. */ + source: _MatSliderThumb; + + /** The MatSlider that was interacted with. */ + parent: _MatSlider; + + /** The new value of the source slider. */ + value: number; +} + export interface _MatSlider { /** Gets the slider thumb input of the given thumb position. */ _getInput(thumbPosition: _MatThumb): _MatSliderThumb | _MatSliderRangeThumb | undefined; diff --git a/tools/public_api_guard/material/slider.md b/tools/public_api_guard/material/slider.md index 176c11ab5a6b..ebbb1771eda6 100644 --- a/tools/public_api_guard/material/slider.md +++ b/tools/public_api_guard/material/slider.md @@ -120,6 +120,13 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, Can static ɵfac: i0.ɵɵFactoryDeclaration; } +// @public @deprecated +export class MatSliderChange { + parent: _MatSlider; + source: _MatSliderThumb; + value: number; +} + // @public export interface MatSliderDragEvent { parent: _MatSlider;