Contenteditable and ng-blur - angularjs

I have a contenteditble div, that I want to reset on blur if it's empty (i.e. if you delete everything and then click outside, it will discard the changes).
If you delete everything but retain focus, then I want it to show a placeholder.
The code below is almost working, but when I delete the last character in the contenteditble div, it's firing the ng-blur event, even though the div still has focus.
<div ng-model="question.QuestionTitle" contenteditable placeholder="Add Question Title"
ng-blur="saveQuestionnaireTitle(question)"></div>
So, when you delete the last character in the div, the placeholder shows for a split second, and then my code inside "saveQuestionnaireTitle" fires, which checks for an empty string repopulates the box - so even though the user hasn't clicked out of the box.
The div appears to loose then quickly regain focus.
Any ideas?

Related

Trimming Draft.js Editor content with the OnBlur event

In order to trim the content of the Draft.js Editor, the following answer works with the onClick event: Draft.js - How to trim contents
However, I'm unable to make it work with the onBlur event.
In both cases it reaches the method, but only when clicking on the button it performs a trimming of the content.
You can reproduce this problem in the following JSFiddle: https://jsfiddle.net/pnfgrhqz/1/
If you add spaces at the beginning and then click the button, it will trim the content, however, if you do the same and then click out of focus, the trimContent method is also triggered, but the content will not be trimmed.
Any idea what am I missing here?
You have two options. you can either call the trimmer with a setTimeout
trimOnBlur = () =>{setTimeout(this.trimContent , 0);}
https://jsfiddle.net/bsv3oegr/1/
or add the onBlur event on the parent div and make it focusable with tabIndex.
tabIndex="0" onBlur={this.trimContent}
https://jsfiddle.net/8rtcgqkb/

Ui-grid triggers ng-blur on wrong textbox when scrolled out of view

We use textboxes on celltemplates instead using an editableCellTemplate.
http://plnkr.co/edit/M8Do1p?p=preview
<input class="grid_textbox text-center"
ng-blur="grid.appScope.quantityChanged(row.entity)"
ng-model="MODEL_COL_FIELD" style="width:80%"/>
We identify changes by catching ng-blur on the textboxes. However, we noticed that when the textbox is out of view when the user scrolls, it does not trigger the ng-blur on the correct textbox.
To reproduce in plnkr
Click on first textbox.
Click on the second textbox, this will display info on the Blur event. This is the expected behavior
To reproduce the error, click Clear and click on the first textbox again.
Scroll down until up to mid-bottom and click on a textbox. It won't output the same message as above.
Is there a way to fix this or a workaround to get the row that was edited?
Update:
I've tried Guranjan's solution and it worked, but another problem came up. I'm not sure if this should be another question but it's still related to scrolling and blur.
To replicate
Click on 1st textbox and input a number
Scroll until it's out of view.
Click on another textbox and edit.
This time just scroll. You can see the cursor focusing on other textboxes and not triggering blur.
Edit one. Then scroll again (mouse wheel or dragging scrollbar). Edit then scroll.
Click on one textbox to trigger blur. It will not display all of the edits.
This is the plunker of Guranjan to try it.
http://plnkr.co/edit/RWM2y7NLC7821c9vQDO6?p=preview
This is because ui-grid reuses the elements. One way to fix your issue is, store the value of current row on focus and use that on blur. For example, create variable in you app scope:
$scope.currentValue = {};
and then you can update this on input focus:
ng-focus="grid.appScope.currentValue = row.entity"
and you can then use $scope.currentValue to do whatever you need to do with it.
Updated Plnkr

Incorrect radio button getting selected for ng-repeat radio buttons

I have a list of radio buttons using ng-repeat.
When I initially load the page and select on the last radio button, the button on it's side gets selected.
This only happens for the first time, i.e. if I click on the last button a second time, it is selected correctly.
<input type="radio" name="rb" value="{{rbCollection.name}}" data-ng-click="open(name)" data-ng-model="Ctrl.selection">
Check this so.
The problem is that ng-click fires before the ng-model code that updates the scope. If you change it to use ng-change, that will fix it. You also need to add ng-change to your text box to update the scope as the user types.

On removing a tag from ngTagsInput, the input field will get focused automatically. Is there a way to prevent this from happening?

I think this code is having some problem. Because when I click on a tag to remove it, the click event will propagate to host div which results in focusing the input box.
Is there a way or any attribute that will prevent the input box from getting focused on removing a tag?

AngularJS ng-class Expression Not Updating Properly

So I'm trying to build a custom autocomplete dropdown for a text input. To do it, I am listening for the keydown event and if it's an up or down arrow press, I'm setting a $scope.arrowSelectedItem variable to the proper one in the list. (As a side note, all the functionality works as far as selecting an item from the list that pops up. All I'm trying to do is highlight the current one that they've marked with the up/down arrows).
On the markup side, the items in the autocomplete list are output with ng-repeat, with ng-repeat="item in itemList". The ng-class expression I'm using is ng-class="{highlighted: item === arrowSelectedItem}". I know that the $scope.arrowSelectedItem is being updated on each arrow press by using console.log, but for some reason the class isn't being updated to the list item properly.
What I've found is that after the first time of hitting an arrow key, if I make the text input box lose focus, then the class is added. Then if I click back in the box, move the arrow to select a different item, click out of the input box, then click back in, the class is added to the new one. I know that sounds weird, but that's what I've found.
What I'm not sure about is why the ng-class expression isn't being evaluated on every arrow key press. Does anyone have any ideas why?
The answer here is that "raw" DOM events which fire outside of one of angular's built in directives (such as click events via ng-click etc) will not trigger a $digest cycle update. Until this happens the $scope properties will not be updated.
If you are in a position where you are listening for DOM events by using another framework, or simply using addEventListener(), you will need to let angular know about any changes by using $scope.$apply(), or by wrapping the code in a $timeout().
If you do this in your event handler, angular will trigger a new $digest cycle update for every keypress and your new scope values will propagate to the view.

Resources