我正在尝试访问当前指令元素之外的DOM元素...用于类似resize的行为,使用外部元素作为句柄并且不要更改目标标记,特别是不使用{{{ 1}}。
我现在正在做的事情是我认为有点不正统,比如使用<ng-content>
:
BrowserDomAdapter
模板看起来像这样:
import {Directive, Input, HostListener} from 'angular2/core';
import {BrowserDomAdapter} from 'angular2/platform/browser';
@Directive
({
selector: '[resizable-handle]',
providers: [BrowserDomAdapter]
})
export class ResizableHandle
{
// get selector from actual directive selector attribute
@Input('resizable-handle') resizableSelector: string;
constructor(private _domAdapter: BrowserDomAdapter){}
@HostListener('mousedown', ['$event'])
startResize(e: MouseEvent)
{
this._domAdapter.query(this.resizableSelector); //... manipulate this native element
}
//... and so on...
}
答案 0 :(得分:3)
谢谢kemsky!
根据您对模板变量的建议,我设计了这个解决方案:
@Directive
({
selector: '[resizable-handle]',
host: { '(click)': 'emitHeight()' }
})
export class ResizableHandle
{
@Input('resizable-handle') resizableSelector: ElementRef;
@Input() targetHeight: any;
@Output() targetHeightChange = new EventEmitter<number>();
emitHeight(){ this.targetHeightChange.emit(100) }
}
@Component
({
selector: 'my-app',
directives: [ResizableHandle],
template: `
<h1>Hello</h1>
<a [resizable-handle]="targetContainer" [(targetHeight)]="containerHeight" href="javascript:void(0)"> [click me!] </a>
<div #targetContainer [style.height.px]="containerHeight"> ... </div>
`
})
export class AppComponent
{
public containerHeight = 25;
}
还要感谢Günter Zöchbauer。我使用父指令构建了另一个解决方案;这是因为手柄和目标实际上并不在同一棵树上,所以我需要一个&#34; root&#34;沟通。
@Directive({ selector: '[resizable-handle]' })
export class ResizableHandle
{
constructor(@Host() @Inject(forwardRef(()=>Resizable)) private _resizable: Resizable){}
// simulate dropping a resize handle here
@HostListener('click', ['$event'])
emitHeight(){ this._resizable.change = Math.max( Math.random()*100, 25 ); }
}
@Directive({ selector: '[resizable-target]' })
export class ResizableTarget
{
constructor(@Host() @Inject(forwardRef(()=>Resizable)) private _resizable: Resizable)
{
this._resizable.change.subscribe( c => this.height = c );
}
@HostBinding('style.height.px') public height;
}
@Directive({ selector: '[resizable]' })
export class Resizable
{
private _change: number;
private _observableChange: Observable<number>;
constructor()
{
this._observableChange = Observable.create( observer => this._change = observer ).share();
}
set change(value){ this._change.next(value) }
get change(){ return this._observableChange; }
}
@Component
({
selector: 'my-app',
directives: [ResizableHandle, ResizableTarget, Resizable],
template: `
<div resizable>
<a resizable-handle href="javascript:void(0)"> [click me!] </a>
<p>...</p>
<div resizable-target> ...a... </div>
<div resizable-target> ...b... </div>
</div>
`,
})
export class AppComponent{}
答案 1 :(得分:2)
我会使用一个指令来应用于直接在目标上进行实际操作的目标元素。
然后你可以使用构造函数注入它。这总是从最近的父节点注入,它找到这个指令。
@Directive({
selector: '[resizable-target]',
host: {'[style.border]': 'border'},
})
export class ResizableTarget {
// change style just to demonstrate this directive can be manipulated
border:string = "solid 3px blue";
@HostBinding('class.reached') reached:boolean = false;
}
@Directive({
selector: '[resizable-handle]',
})
export class ResizableHandle {
// inject the target
constructor(private _target:ResizableTarget) {}
@HostListener('mousedown', ['$event'])
startResize(e: MouseEvent) {
// call methods or set properties in order to manipulate the target
this._target.reached = true;
this._target.border = "solid 3px red";
}
}
@Component({
selector: 'my-app',
directives: [ResizableTarget, ResizableHandle],
template: `
<h1>Hello</h1>
<div resizable-target>
<div>
<div> some content
<div resizable-handle>handle</div>
</div>
</div>
</div>
`,
})
export class AppComponent {
}
答案 2 :(得分:1)
您可以使用模板变量:
@Input('resizable-handle') resizableSelector: ElementRef;
<a [resizable-handle]="target-container"> ... </a>
<!-- ...somewhere further, on a different level, the target I don't want to touch in order to get this working... -->
<div #target-container> ... </div>