Angular6 HTML 具有不断变化的下拉选项的输入字段
Angular6 HTML Input-Field with changing Dropdown Options
我想实现一个 HTML5 支持用户输入的输入字段。
想象一下用户不仅要输入随机文本,还必须遵循特定语法的情况:
rule: <expression> {<op><expression>}
expression: <Object>[<property>] is <State>
property: key=value
State: active | inactive | valid .....
我想到了一个状态机,如果用户输入这个,那么用户就处于状态 2,否则他就处于状态 3,依此类推。
我找到了以下内容:
<input list="browsers">
<datalist id="browsers">
<option value="Internet Explorer">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
这几乎就是我所需要的。但正如您所见,它有点太静态了。我想更新选项,它们应该随时出现,而不仅仅是第一次选择。
因此,如果用户开始一个新的表达式,那么选项会发生变化,然后在他进行一些输入后它们会再次发生变化。选项应该是可点击的,选项的值应该添加到前面的文本中。
我想到了一个解决方案,我在更改 innerHtml 的输入字段下方添加了一个标签,但这似乎不是一个好的解决方案,有什么更好的主意吗?
自己用下面的代码解决了这个问题:
component.ts:
export class Component {
ruleInputFocused:boolean = false;
selectActive: boolean=false;
options: string[];
constructor() {
this.setState(0);
}
ngOnInit() {
}
changeSelective(value:boolean){
this.selectActive= value;
}
changeFocused(value:boolean){
if(this.selectActive == false){
this.ruleInputFocused = value;
}
}
setState(stateNumber: number){
this.options = [];
this.positionCounter = -1;
if(stateNumber == 0){
this.options.push("(");
this.options.push("Object[key=value] ");
}
}
optionClicked(i){
this.ruleText = this.ruleText.concat(this.options[i]);
document.getElementById("ruleInput").focus();
}
positionCounter = -1;
@HostListener('document:keydown', ['$event'])
public handleKeyboardEvent(event: KeyboardEvent): void {
if(this.ruleInputFocused){
if(event.key == 'ArrowDown'){
this.positionCounter++;
if(this.positionCounter>this.options.length -1){
this.positionCounter = 0;
}
console.log(this.positionCounter);
}else if(event.key == 'ArrowUp'){
this.positionCounter--;
if(this.positionCounter<0){
this.positionCounter = this.options.length -1
}
}else if(event.key == 'Enter'){
if(this.positionCounter != -1){
this.optionClicked(this.positionCounter);
}
}
}
}
}
HTML:
<div class="mainContainer">
<div class="ruleInputDiv">
<div class="divLabel">Rule: </div>
<input id="ruleInput" type="text" autocorrect="off"
(focus)="changeFocused(true)" (focusout)="changeFocused(false)" [(ngModel)]="ruleText" >
<button id="ruleInputCheckButton" (click)="checkRule()">Check</button>
</div>
<!--[hidden]=!ruleInputFocused-->
<div class="optionsDiv" id="optionsDiv" [hidden]="!ruleInputFocused">
<div class="singleOption" *ngFor="let option of options; let i = index"
[ngClass]="{selected: positionCounter===i}" (click)="optionClicked(i)" (mouseenter) ="changeSelective(true)" (mouseleave) ="changeSelective(false)">
{{option}}
<div class="verticalBorderDiv"></div>
</div>
</div>
</div>
CSS:
我想实现一个 HTML5 支持用户输入的输入字段。
想象一下用户不仅要输入随机文本,还必须遵循特定语法的情况:
rule: <expression> {<op><expression>}
expression: <Object>[<property>] is <State>
property: key=value
State: active | inactive | valid .....
我想到了一个状态机,如果用户输入这个,那么用户就处于状态 2,否则他就处于状态 3,依此类推。
我找到了以下内容:
<input list="browsers">
<datalist id="browsers">
<option value="Internet Explorer">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
这几乎就是我所需要的。但正如您所见,它有点太静态了。我想更新选项,它们应该随时出现,而不仅仅是第一次选择。
因此,如果用户开始一个新的表达式,那么选项会发生变化,然后在他进行一些输入后它们会再次发生变化。选项应该是可点击的,选项的值应该添加到前面的文本中。
我想到了一个解决方案,我在更改 innerHtml 的输入字段下方添加了一个标签,但这似乎不是一个好的解决方案,有什么更好的主意吗?
自己用下面的代码解决了这个问题:
component.ts:
export class Component {
ruleInputFocused:boolean = false;
selectActive: boolean=false;
options: string[];
constructor() {
this.setState(0);
}
ngOnInit() {
}
changeSelective(value:boolean){
this.selectActive= value;
}
changeFocused(value:boolean){
if(this.selectActive == false){
this.ruleInputFocused = value;
}
}
setState(stateNumber: number){
this.options = [];
this.positionCounter = -1;
if(stateNumber == 0){
this.options.push("(");
this.options.push("Object[key=value] ");
}
}
optionClicked(i){
this.ruleText = this.ruleText.concat(this.options[i]);
document.getElementById("ruleInput").focus();
}
positionCounter = -1;
@HostListener('document:keydown', ['$event'])
public handleKeyboardEvent(event: KeyboardEvent): void {
if(this.ruleInputFocused){
if(event.key == 'ArrowDown'){
this.positionCounter++;
if(this.positionCounter>this.options.length -1){
this.positionCounter = 0;
}
console.log(this.positionCounter);
}else if(event.key == 'ArrowUp'){
this.positionCounter--;
if(this.positionCounter<0){
this.positionCounter = this.options.length -1
}
}else if(event.key == 'Enter'){
if(this.positionCounter != -1){
this.optionClicked(this.positionCounter);
}
}
}
}
}
HTML:
<div class="mainContainer">
<div class="ruleInputDiv">
<div class="divLabel">Rule: </div>
<input id="ruleInput" type="text" autocorrect="off"
(focus)="changeFocused(true)" (focusout)="changeFocused(false)" [(ngModel)]="ruleText" >
<button id="ruleInputCheckButton" (click)="checkRule()">Check</button>
</div>
<!--[hidden]=!ruleInputFocused-->
<div class="optionsDiv" id="optionsDiv" [hidden]="!ruleInputFocused">
<div class="singleOption" *ngFor="let option of options; let i = index"
[ngClass]="{selected: positionCounter===i}" (click)="optionClicked(i)" (mouseenter) ="changeSelective(true)" (mouseleave) ="changeSelective(false)">
{{option}}
<div class="verticalBorderDiv"></div>
</div>
</div>
</div>
CSS: