Issue
I want to implement an HTML5 Input field which supports the user with his input.
Imagine the case that the user has to enter not just random text, he has to follow a specific grammar:
rule: <expression> {<op><expression>}
expression: <Object>[<property>] is <State>
property: key=value
State: active | inactive | valid .....
I thought about a state machine like if the user enters this then the user is in state 2 and if not he is in state 3 and so on.
I found the following:
<input list="browsers">
<datalist id="browsers">
<option value="Internet Explorer">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
And it is nearly what I need. But as you can see it is a little bit too static. I want to update the options and they should appear at any time not just for the first selection.
So if the user starts a new expression then options change then they change again after he did some input. The options should be clickable and the value of the options should be added to the previous text.
I thought about a solution where I add just a tag below the input field where I change the innerHtml but this seems not to be a good solution, what is a better idea?
Solution
Solved it myself with the code below:
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:
Answered By - Korbson
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.