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
Spec style #22719
Spec style #22719
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -866,7 +866,7 @@ function generatePropertyAliases(lNodeFlags: number, direction: BindingDirection | |
} | ||
|
||
/** | ||
* Add or remove a class in a classList. | ||
* Add or remove a class in a `classList` on a DOM element. | ||
* | ||
* This instruction is meant to handle the [class.foo]="exp" case | ||
* | ||
|
@@ -875,7 +875,7 @@ function generatePropertyAliases(lNodeFlags: number, direction: BindingDirection | |
* renaming as part of minification. | ||
* @param value A value indicating if a given class should be added or removed. | ||
*/ | ||
export function elementClass<T>(index: number, className: string, value: T | NO_CHANGE): void { | ||
export function elementClassNamed<T>(index: number, className: string, value: T | NO_CHANGE): void { | ||
if (value !== NO_CHANGE) { | ||
const lElement = data[index] as LElementNode; | ||
if (value) { | ||
|
@@ -889,6 +889,29 @@ export function elementClass<T>(index: number, className: string, value: T | NO_ | |
} | ||
} | ||
|
||
/** | ||
* Set the `className` property on a DOM element. | ||
* | ||
* This instruction is meant to handle the `[class]="exp"` usage. | ||
* | ||
* `elementClass` instruction writes the value to the "element's" `className` property. | ||
* | ||
* @param index The index of the element to update in the data array | ||
* @param value A value indicating a set of classes which should be applied. The method overrides | ||
* any existing classes. The value is stringified (`toString`) before it is applied to the | ||
* element. | ||
*/ | ||
export function elementClass<T>(index: number, value: T | NO_CHANGE): void { | ||
if (value !== NO_CHANGE) { | ||
// TODO: This is a naive implementation which simply writes value to the `className`. In the | ||
// future | ||
// we will add logic here which would work with the animation code. | ||
const lElement: LElementNode = data[index]; | ||
isProceduralRenderer(renderer) ? renderer.setProperty(lElement.native, 'className', value) : | ||
lElement.native['className'] = stringify(value); | ||
} | ||
} | ||
|
||
/** | ||
* Update a given style on an Element. | ||
* | ||
|
@@ -900,31 +923,65 @@ export function elementClass<T>(index: number, className: string, value: T | NO_ | |
* @param sanitizer An optional function used to transform the value typically used for | ||
* sanitization. | ||
*/ | ||
export function elementStyle<T>( | ||
export function elementStyleNamed<T>( | ||
index: number, styleName: string, value: T | NO_CHANGE, suffix?: string): void; | ||
export function elementStyle<T>( | ||
export function elementStyleNamed<T>( | ||
index: number, styleName: string, value: T | NO_CHANGE, sanitizer?: Sanitizer): void; | ||
export function elementStyle<T>( | ||
export function elementStyleNamed<T>( | ||
index: number, styleName: string, value: T | NO_CHANGE, | ||
suffixOrSanitizer?: string | Sanitizer): void { | ||
if (value !== NO_CHANGE) { | ||
const lElement = data[index] as LElementNode; | ||
const lElement: LElementNode = data[index]; | ||
if (value == null) { | ||
isProceduralRenderer(renderer) ? | ||
renderer.removeStyle(lElement.native, styleName, RendererStyleFlags3.DashCase) : | ||
lElement.native.style.removeProperty(styleName); | ||
lElement.native['style'].removeProperty(styleName); | ||
} else { | ||
let strValue = | ||
typeof suffixOrSanitizer == 'function' ? suffixOrSanitizer(value) : stringify(value); | ||
if (typeof suffixOrSanitizer == 'string') strValue = strValue + suffixOrSanitizer; | ||
isProceduralRenderer(renderer) ? | ||
renderer.setStyle(lElement.native, styleName, strValue, RendererStyleFlags3.DashCase) : | ||
lElement.native.style.setProperty(styleName, strValue); | ||
lElement.native['style'].setProperty(styleName, strValue); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Set the `style` property on a DOM element. | ||
* | ||
* This instruction is meant to handle the `[style]="exp"` usage. | ||
* | ||
* | ||
* @param index The index of the element to update in the data array | ||
* @param value A value indicating if a given style should be added or removed. | ||
* The expected shape of `value` is an object where keys are style names and the values | ||
* are their corresponding values to set. If value is falsy than the style is remove. An absence | ||
* of style does not cause that style to be removed. `NO_CHANGE` implies that no update should be | ||
* performed. | ||
*/ | ||
export function elementStyle<T>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per comment above I think we should keep the . Unless you feel strongly There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it apply with |
||
index: number, value: {[styleName: string]: any} | NO_CHANGE): void { | ||
if (value !== NO_CHANGE) { | ||
// TODO: This is a naive implementation which simply writes value to the `style`. In the future | ||
// we will add logic here which would work with the animation code. | ||
const lElement = data[index] as LElementNode; | ||
if (isProceduralRenderer(renderer)) { | ||
renderer.setProperty(lElement.native, 'style', value); | ||
} else { | ||
const style = lElement.native['style']; | ||
for (let i = 0, keys = Object.keys(value); i < keys.length; i++) { | ||
const styleName: string = keys[i]; | ||
const styleValue: any = (value as any)[styleName]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drop There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can't it is an error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still true with edit: oh nevermind this one. Must be because |
||
styleValue == null ? style.removeProperty(styleName) : | ||
style.setProperty(styleName, styleValue); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
////////////////////////// | ||
//// Text | ||
////////////////////////// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util'; | ||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core'; | ||
import * as $r3$ from '../../../src/core_render3_private_export'; | ||
import {renderComponent, toHtml} from '../render_util'; | ||
import {ComponentFixture, renderComponent, toHtml} from '../render_util'; | ||
|
||
/// See: `normative.md` | ||
describe('elements', () => { | ||
|
@@ -168,7 +168,7 @@ describe('elements', () => { | |
$r3$.ɵE(0, 'div'); | ||
$r3$.ɵe(); | ||
} | ||
$r3$.ɵk(0, 'foo', $r3$.ɵb(ctx.someFlag)); | ||
$r3$.ɵkn(0, 'foo', $r3$.ɵb(ctx.someFlag)); | ||
} | ||
}); | ||
// /NORMATIVE | ||
|
@@ -202,8 +202,8 @@ describe('elements', () => { | |
$r3$.ɵE(0, 'div'); | ||
$r3$.ɵe(); | ||
} | ||
$r3$.ɵs(0, 'color', $r3$.ɵb(ctx.someColor)); | ||
$r3$.ɵs(0, 'width', $r3$.ɵb(ctx.someWidth), 'px'); | ||
$r3$.ɵsn(0, 'color', $r3$.ɵb(ctx.someColor)); | ||
$r3$.ɵsn(0, 'width', $r3$.ɵb(ctx.someWidth), 'px'); | ||
} | ||
}); | ||
// /NORMATIVE | ||
|
@@ -251,7 +251,7 @@ describe('elements', () => { | |
$r3$.ɵe(); | ||
} | ||
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.someString + 1)); | ||
$r3$.ɵk(0, 'foo', $r3$.ɵb(ctx.someString == 'initial')); | ||
$r3$.ɵkn(0, 'foo', $r3$.ɵb(ctx.someString == 'initial')); | ||
} | ||
}); | ||
// /NORMATIVE | ||
|
@@ -264,5 +264,36 @@ describe('elements', () => { | |
$r3$.ɵdetectChanges(comp); | ||
expect(toHtml(comp)).toEqual('<div class="" id="changed1" style="color: red;"></div>'); | ||
}); | ||
|
||
it('should bind [class] and [style] to the element', () => { | ||
type $StyleComponent$ = StyleComponent; | ||
|
||
@Component( | ||
{selector: 'style-comp', template: `<div [class]="classExp" [style]="styleExp"></div>`}) | ||
class StyleComponent { | ||
classExp: string[]|string = 'some-name'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we plan to support There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe, not sure yet... |
||
styleExp: {[name: string]: string} = {'background-color': 'red'}; | ||
|
||
// NORMATIVE | ||
static ngComponentDef = $r3$.ɵdefineComponent({ | ||
type: StyleComponent, | ||
tag: 'style-comp', | ||
factory: function StyleComponent_Factory() { return new StyleComponent(); }, | ||
template: function StyleComponent_Template(ctx: $StyleComponent$, cm: $boolean$) { | ||
if (cm) { | ||
$r3$.ɵE(0, 'div'); | ||
$r3$.ɵe(); | ||
} | ||
$r3$.ɵk(0, $r3$.ɵb(ctx.classExp)); | ||
$r3$.ɵs(0, $r3$.ɵb(ctx.styleExp)); | ||
} | ||
}); | ||
// /NORMATIVE | ||
} | ||
|
||
const styleFixture = new ComponentFixture(StyleComponent); | ||
expect(styleFixture.html) | ||
.toEqual(`<div class="some-name" style="background-color: red;"></div>`); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
elementClass
variant seems to be the most specific / counter-intuitive. KeepelementClass()
for this one and find a meaningful name for the other one ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever name we come up with it should be consistent with style. I am open for new name but it should be consistent.