Form rapidly tabs between form fields - html

When editing a field I click off the window and it loses focus. Then when I click back into the window in a different field, the focus will rapidly tab between the two form fields.
This issue occurs occurs in Chrome, IE, and Firefox. The form fields are being pulled from a questionnaire json file for one part, but I have noticed it happening in the fields that aren't pulled from a questionnaire as well.
Below is a sample of the html and angular code that creates the form.
<ng-form name="personalForm">
<div layout="row" layout-align="center center" ng-repeat="section in sections" ng-show="currentSection >= $index+1" id="section_{{$index}}">
<md-list id="personalQnsList" layout="row" layout-align="start center" flex="90">
<!-- Questions Layout -->
<div layout="column" layout-align="start center" flex="100" role="listitem">
<div class="row sectionLine" layout="row" id='personal_{{$index}}' layout-align="start center" ng-repeat="personalQuestion in section.questions track by $index" ng-if="section.questions[$index-1].valid || $first" ng-class="{'animate-if':$index!=0}">
<div class="row" layout-align="start center" ng-class="{'ssn': personalQuestion.fieldType == 'ssn' }">
<!-- 3 is added to the index to account for the previous questions -->
<dynamic-question section-name="section.name" form-name="personalForm" question-index="$index + 3" question-model="personalQuestion" result-produced="resultProduced(result, personalQuestion.fieldType, personalQuestion.fieldMapping)"
layout-align="start center" layout-align-xs="center center"></dynamic-question>
</div>
<!-- <md-button class="info-icon" ng-if="personalQuestion.info"> <md-icon></md-icon>
<md-tooltip class="infoTooltip" md-direction="right"> {{personalQuestion.id |translate}}</md-tooltip> </md-button> -->
</div>
</div>
</md-list>
</div>
<div layout="column" layout-align="center center">
<md-button class="md-primary md-raised" ng-if="pCtrl.continueFlag" ng-click="pCtrl.reviewPersonalInformation()" aria-label="Continue">Continue</md-button>
<!-- <md-button class="md-primary md-raised" ng-if="pCtrl.continueFlag && pCtrl.profileContinue" ng-click="pCtrl.reviewPersonalInformation()" aria-label="Continue">Continue</md-button> -->
<div ng-show="pCtrl.errorMessageFlag" class="error_Msg text-center">There is an error with the information you provided. Please check your fields again</div>
<div ng-show="pCtrl.errorMessageFlag" class="error_Msg text-center">Please check {{pCtrl.missingFields}} fields again</div>
</div>
</ng-form>

Probably you have:
1) A Javascript "global" event (I'm 90% sure that it's a Jquery event) checking on every interaction a user has with your app elements.
2) This javascript event (maybe a .focus .click variation) is forcing to always focus one of the element (let's call it element "x"). That's why it's happening that when the user clicks on any another element (this element probably has a javascript event too with a focus instruction inside) different of element "x" the focus try to return back to the element "x"
3) Both focus instruction on the javascript "global" element are "fighting" each other to have the focus on the element they handle (event "x" to focus "x" for element "x" and event "n" to focus "n" for element "n" )
4) This javascript functions maybe are bounded to one or maybe more class names of your element
5) I'm specially curious about these two lines classes and posibly bounded javascript events:
<div class="row sectionLine" layout="row" id='personal_{{$index}}' layout-align="start center" ng-repeat="personalQuestion in section.questions track by $index" ng-if="section.questions[$index-1].valid || $first" ng-class="{'animate-if':$index!=0}">
<div class="row" layout-align="start center" ng-class="{'ssn': personalQuestion.fieldType == 'ssn' }">
To conclude: All I had mentioned above is the most common thing to happen and since you don't provide necessary code to let me test your app is the most accurate answer I can give you.

Related

mwlDraggable (Drag & Drop) - minimum length of move

I have a problem with mat-card, that is draggable and also contains some button. Unfortunately, on my PC button (click) don't work at all, on my collegue it works sometimes. We think that it can be caused as click is treated as dragging element. Is there anyway to set minimal length of move (dragging), which causes starting treating object as moved?
It was tested on 2 machines - the same code, different behaviour - one one (click) on button is never executed, on second one - sometimes.
What I found now on my computer - while I'm debugging it (Chrome) - when I move my mouse cursor over cards on one of cases occurring this - I get blue "shadow" over the whole app from debugger, but button is clickable - it works as I expected, otherwise - not.
<mat-card mwlDraggable *ngFor="let item of items; let i = index" [dragActiveClass]="'field-dragged'"
[dropData]="item" (dragEnd)="itemFieldDragEnd($event, item)">
<mat-card-content>
<div class="pull-left m-t-5">
{{item.name}}
<div class="field-meta truncate">
{{item.desc}}
</div>
</div>
<div class="pull-right">
<button mat-icon-button (click)="onItemFieldClick($event, item)" matTooltip="somehint">
<mat-icon class="md-24">arrow_forward_ios</mat-icon>
</button>
</div>
</mat-card-content>
</mat-card>
I want to obtain way to force mwlDraggable to become draggable only if it was moved really by let's say 10px, not before. Or any other solution that would work for that problem.
I found solution on github: https://github.com/mattlewis92/angular-draggable-droppable/issues/53
Exemplary fully implemented solution using above:
<mat-card mwlDraggable *ngFor="let item of items; let i = index" [dragActiveClass]="'field-dragged'"
[dropData]="item" (dragEnd)="itemFieldDragEnd($event, item)"
[validateDrag]="dragThresholdValidator">
<mat-card-content>
<div class="pull-left m-t-5">
{{item.name}}
<div class="field-meta truncate">
{{item.desc}}
</div>
</div>
<div class="pull-right">
<button mat-icon-button (click)="onItemFieldClick($event, item)" matTooltip="somehint">
<mat-icon class="md-24">arrow_forward_ios</mat-icon>
</button>
</div>
</mat-card-content>
</mat-card>
public dragThresholdValidator({ x, y }: any): boolean {
const min_drag_threshold = 5;
return Math.abs(x) > min_drag_threshold || Math.abs(y) > min_drag_threshold;
}

Add class with [ngClass] depending on local html condition

I have used [ngClass] in the past, applying classes depending on the Boolean value of a variable held in the javascript/typescript before. However I am wondering if it is possible to apply it based on a local HTML boolean value or not?
ie.
<div class="card" *ngFor="let item of data" #panel ngClass="{expanded: isExpanded}">
<div class="header">
<div class="itemName">Text</div>
<div class="itemDir">Some more text</div>
<mat-icon *ngIf="!panel.isExpanded" (click)="panel.isExpanded=true">edit</mat-icon>
<mat-icon *ngIf="panel.isExpanded" (click)="panel.isExpanded=false">cancel</mat-icon>
</div>
</div>
Here, I am displaying one of two icons, depending on the local isExpanded variable defined within the HTML and not the backend.
I am wanting to apply a class based on this value... is it possible?
Here is what I am working on
use like [class.expanded]="isExpanded". binding to class.expanded trumps the class attribute
<div class="card" *ngFor="let item of data" #panel [class.expanded]="panel.isExpanded" [class.notExpanded]="!panel.isExpanded">
you can use *ngIf="true as isExpanded" to make variable on the template
<div class="card" *ngFor="let item of [1,2,3,4];" >
<div class="header" *ngIf="true as isExpanded" ngClass="{expanded: !isExpanded}">
<div class="itemName">Text</div>
<div class="itemDir">Some more text</div>
<div *ngIf="isExpanded" (click)="isExpanded=!isExpanded">edit</div>
<div *ngIf="!isExpanded" (click)="isExpanded=!isExpanded">cancel</div>
</div>
</div>
stackblitz demo 👍👍
<div class="card" *ngFor="let item of data" #panel ngClass="{expanded: isExpanded}">
<div class="header">
<div class="itemName">{{item.name}}</div>
<div class="itemDir">{{item.directory}}</div>
<mat-icon *ngIf="!isExpanded;else other_content" (click)="isExpanded=true">edit</mat-icon>
<ng-template #other_content>Other Icon goes here</ng-template>
</div>
You can refer the above code which use If and else by template referenced variable which properly toggle between both icon and non Icon

Use ng-repeat and have one item of a list mandatory

I'am learning AngularJs (v1.6) using Angular Material and I'am stuck on a small but annoying display problem.
I've created a simple list of items (fruits) with switches buttons. The user can switch on the button if the fruits is present. I used ng-repeat to display each elements of my list...
Then, I tried to have got only one of my switches button mandatory, so I used the word "required"...like this:
The HTML:
<md-list-item ng-repeat="(key, value) in $ctrl.vegetables.fruits">
<p>{{'vegetables.fruits.' + key | translate}}</p>
<md-switch class="md-primary" ng-model="$ctrl.vegetables.fruits[key]" required>
<br/>
<div class="warning" ng-show="key === 'banana'" >Ce champ est obligatoire</div>
</md-switch>
</md-list-item>
But if I put it in the md-switch div, all the items of my list are required...
If I display the elements of my list one by one, I can required only one element.. but I would like to keep the ng-repeat.
So this is my question: How can I do to have only one of my item mandatory ?
Thanks
I think this is as you want :
<md-list-item >
<p ng-repeat-start="(key, value) in $ctrl.vegetables.fruits">{{'vegetables.fruits.' + key | translate}}</p>
<md-switch ng-repeat-end class="md-primary" ng-model="$ctrl.vegetables.fruits[key]" required>
<br/>
<div class="warning" ng-show="key === 'banana'" >Ce champ est obligatoire</div>
</md-switch>
</md-list-item>

How to show/hide in Angular2

I have a component that show/hide element by clicking a button.
This is my html
<div *ngFor="let history of histories | sortdate: '-dateModified'">
<p><b>{{ history.remarks }}</b> - <i>{{history.dateModified | date:'short'}}</i></p>
<a href="google.com"
[class.datatable-icon-right]="history.$$expanded"
[class.datatable-icon-down]="!history.$$expanded"
title="Expand/Collapse Row"
(click)="toggleExpandRow(history)"></a>
<!-- hide/show this by clicking the button above.-->
<div *ngFor="let step of history.steps; let i = index">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
<hr />
</div>
and my .ts
toggleExpandRow(row) {
console.log('Toggled Expand Row!', row);
//row
return false;
}
trying to search but, can't find any same sample.
On jquery, I can do this, but on Angular2, I am having hard time to figure this.
There are two options:
1- You can use the hidden directive to show or hide any element
<div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
2- You can use the ngIf control directive to add or remove the element. This is different of the hidden directive because it does not show / hide the element, but it add / remove from the DOM. You can loose unsaved data of the element. It can be the better choice for an edit component that is cancelled.
<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
Use the ngIf in your repeated rows. Create a boolean property called showStep to indicate whether the row should be expanded or not.
<div *ngFor="let step of history.steps; let i = index" ngIf="history.showStep">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
Then, in your .ts file:
toggleExpandRow(history) {
history.showStep = !history.showStep
//note the same porperty of showStep that is used in your html
}
Extra:
In fact, to save a few lines of codes, you don't even need the toggleExpandRow function at all. You can do it inline in your html:
//other attributes omitted for brevity
<a (click)="history.showStep = !history.showStep">

How to get the range/innerHtml of an item when item is drag to timeline vis.js?

1.I have an items in one div
2.I am dragging that items and dropping in the timeline.
3.so At the time of dropping.I want to get the timeline range of that particular item.
I used ng-draggable,timeline vis.js libraries.
Items in one div code :
<div class="timeline-elements-left-column">
<md-card class="timeline-elements-container"
ng-repeat="element in vm.elementAndStages">
<md-toolbar md-scroll-shrink class="timeline-selected-elements drag-object">
<div layout="row"
id="translation-icon-move"
ng-drag="vm.isDragging"
ng-mousedown="vm.StartDragging(element, event)"
ng-drag-data="element">
<div flex class="timeline-selected-elements-text">
<span>{{element.selectedElement.description}}</span>
</div>
<div class="timeline-selected-elements-icon">
<md-icon ng-show="element.selectedElement.collapsed"
class="zmdi zmdi-chevron-up"
ng-click="vm.Collapse(element.selectedElement)">
</md-icon>
<md-icon ng-hide="element.selectedElement.collapsed"
class="zmdi zmdi-chevron-down"
ng-click="vm.Collapse(element.selectedElement)">
</md-icon>
</div>
<div class="timeline-selected-elements-icon timeline-selected-elements-icon-drag">
<md-icon class="zmdi zmdi-more-vert"></md-icon>
</div>
</div>
</md-toolbar>
</md-card>
</div>
4.So here vm.StartDragging() is the function to Drag the event.
so at the time of start Dragging function
function StartDragging(data:stage,event :any){
console.log(this.timeline.getEventProperties(event));
}
so at the time of dragging its working fine.
Problem is at drop-success.
Dropping success on timeline but I am unable to get that range where user is dropping the item in timeline.
Dropping code in Html
<div class="vis-group" ng-drop="true" ng-drop-success="vm.OnDropComplete($index, $data, $event,0)" ng-drag-stop="vm.StopDragging($event)" id="group0" style="height: 173px;">
Here Dropping is fine.
5.OnDropComplete function code
OnDropComplete(index :number,stage:any,event: any, groupId: number): void {
var indexToRemove: number = -1;
this.pendingChanges = [];
console.log(this.timeline.getEventProperties(event));
}
so console.log(this.timeline.getEventProperties(event)); this line generating error.Here Event is ok , but event.target is undefined.
This is a tricky task you are trying to solve. Since the vis timeline is dynamic (can be zoomed or scrolled) you do not have a static point you can use as a referencing point to where the item is dropped.
When I tried to solve a similar issue I was using a combination of document.getElementFromPoint() (using the coordinates from the drop event) and the time axis in the timeline to get the nearest point to where the user dropped the item. Using those information, I would add the item at the specific place.
I hope this puts you on the right track.