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;