我正在实现一个Angular 2属性指令,允许我向这样的元素添加自定义上下文菜单:
<p context-menu="myItems">Hello world</p>
Run Code Online (Sandbox Code Playgroud)
该指令添加了一个鼠标事件处理程序来捕获右键单击,然后想法是构造一个上下文菜单,将其添加到DOM,然后在用户完成时将其销毁.
我有一个实现上下文菜单本身的组件.我想构造该组件,在其上调用一个方法来设置项目列表,然后将其添加到DOM.
看起来我可以用AppViewManager.createHostViewInContainer来做到这一点.这是一个合适的方法吗?如果是这样,有没有办法构造/获取ElementRef,document.body
以便我可以告诉createHostViewInContainer在那里构建组件?显然我不希望我的菜单被剪切到我正在添加上下文菜单的元素中.
Abd*_*yer 27
我认为这是一个很好的方法.
您需要1个服务,1个组件和1个指令.
说明:
服务
ContextMenuService
:
{event:MouseEvent,obj:any[]}
要订阅的类型的主题ContextMenuHolderComponent
,并从中接收值ContextMenuDirective
码:
import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Rx';
@Injectable()
export class ContextMenuService{
public show:Subject<{event:MouseEvent,obj:any[]}> = new Subject<{event:MouseEvent,obj:any[]}>();
}
Run Code Online (Sandbox Code Playgroud)
并将其添加到提供商列表中 bootstrap()
bootstrap(AppComponent,[ContextMenuService]);
Run Code Online (Sandbox Code Playgroud)
组件
ContextMenuHolderComponent
:
AppComponent
,它有一个fixed
位置.它订阅subject
in ContextMenuService
接收:
{title:string,subject:Subject}[]
,主题用于发送菜单内的点击值它有一个(document:click)
事件监听器,可以在菜单外点击菜单时关闭菜单.
码:
@Component({
selector:'context-menu-holder',
styles:[
'.container{width:150px;background-color:#eee}',
'.link{}','.link:hover{background-color:#abc}',
'ul{margin:0px;padding:0px;list-style-type: none}'
],
host:{
'(document:click)':'clickedOutside()'
},
template:
`<div [ngStyle]="locationCss" class="container">
<ul>
<li (click)="link.subject.next(link.title)" class="link" *ngFor="#link of links">
{{link.title}}
</li>
</ul>
</div>
`
})
class ContextMenuHolderComponent{
links = [];
isShown = false;
private mouseLocation :{left:number,top:number} = {left:0;top:0};
constructor(private _contextMenuService:ContextMenuService){
_contextMenuService.show.subscribe(e => this.showMenu(e.event,e.obj));
}
// the css for the container div
get locationCss(){
return {
'position':'fixed',
'display':this.isShown ? 'block':'none',
left:this.mouseLocation.left + 'px',
top:this.mouseLocation.top + 'px',
};
}
clickedOutside(){
this.isShown= false; // hide the menu
}
// show the menu and set the location of the mouse
showMenu(event,links){
this.isShown = true;
this.links = links;
this.mouseLocation = {
left:event.clientX,
top:event.clientY
}
}
}
Run Code Online (Sandbox Code Playgroud)
并将其添加到根组件:
@Component({
selector: 'my-app',
directives:[ContextMenuHolderComponent,ChildComponent],
template: `
<context-menu-holder></context-menu-holder>
<div>Whatever contents</div>
<child-component></child-component>
`
})
export class AppComponent { }
Run Code Online (Sandbox Code Playgroud)
最后一个,
ContextMenuDirective
:
contextmenu
向主机元素添加一个事件.ContextMenuHolderComponent
.码:
@Directive({
selector:'[context-menu]',
host:{'(contextmenu)':'rightClicked($event)'}
})
class ContextMenuDirective{
@Input('context-menu') links;
constructor(private _contextMenuService:ContextMenuService){
}
rightClicked(event:MouseEvent){
this._contextMenuService.show.next({event:event,obj:this.links});
event.preventDefault(); // to prevent the browser contextmenu
}
}
Run Code Online (Sandbox Code Playgroud)
而已.您现在需要做的就是将[context-menu]
指令附加到元素并将其绑定到项列表.例如:
@Component({
selector:'child-component',
directives:[ContextMenuDirective],
template:`
<div [context-menu]="links" >right click here ... {{firstRightClick}}</div>
<div [context-menu]="anotherLinks">Also right click here...{{secondRightClick}}</div>
`
})
class ChildComponent{
firstRightClick; secondRightClick;
links;
anotherLinks;
constructor(){
this.links = [
{title:'a',subject:new Subject()},
{title:'b',subject:new Subject()},
{title:'b',subject:new Subject()}
];
this.anotherLinks = [
{title:'link 1',subject:new Subject()},
{title:'link 2',subject:new Subject()},
{title:'link 3',subject:new Subject()}
];
}
// subscribe to subjects
ngOnInit(){
this.links.forEach(l => l.subject.subscribe(val=> this.firstCallback(val)));
this.anotherLinks.forEach(l => l.subject.subscribe(val=> this.secondCallback(val)))
}
firstCallback(val){
this.firstRightClick = val;
}
secondCallback(val){
this.secondRightClick = val;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17616 次 |
最近记录: |