ngblur and ngfocus on options list shown / hidden in Angular - angularjs

When using select and option the ngblur isn't triggered once I click off the list without selecting anything.
I need to know when the options of the select and shown or hidden. Is there a directive that supports this ?
I can use ngblur and ngfocus on the Select element but nothing is ever fired on the options being shown or hidden. Any ideas?

I've run some tests on fiddle.
https://jsfiddle.net/EternalLight/x7dxkok2/
<div ng-app="testTt">
<div ng-controller="Controller" style="padding:2em;">
<select ng-focus="onFocus()" ng-blur="onBlur()">
<option>Test 1</option>
<option>Test 2</option>
</select>
<p>{{status}}</p>
</div>
</div>
It seems that the blur event is fired when you click outside of the element when the option list is hidden. When you open the option list, and then click outside, the <select> is still in focus - you can see it by the blue (or any other, depending on your browser) outline around it. Honestly, I would use ng-blur, since it takes another outside click to trigger it, and there's no way for a user to get around it.

Related

UI Bootstrap datepicker duplicated when appended to body

I'm using ui.bootstrap.datepickerPopup in a filter header template inside ui.grid. This lets me filter rows by date. I also have a button inside the grid menu that toggles grid.options.enableFiltering.
Due to alignment issues with ui-grid, I have datepicker-append-to-body set to true for my datepickers. The first time I enable filtering, everything works fine. However, when I disable filtering and re-enable it, I get duplicate datepickers.
This is what the problem looks like:
I think the problem is that each time the filters are enabled, the following div is appended to the DOM and never removed when the filters are disabled.
<div uib-datepicker-popup-wrap=""
ng-model="date"
ng-change="dateSelection(date)"
template-url="uib/template/datepickerPopup/popup.html"
class="ng-pristine ng-untouched ng-valid ng-scope ng-empty ng-valid-date-disabled"
>
<!-- ngIf: isOpen -->
</div>
Here's a simplified plunker: http://plnkr.co/edit/eYZt87j2O6A5xhjHj5ZG
I get the same issue if I only use one datepicker inside the Time Range filter header.
Any ideas are greatly appreciated! Don't want to use jQuery.
I don't have an answer on why this is happening but a solution without jQuery would be to remove the pop-up when triggering the filter toggle using document.querySelectorAll()
var elements = document.querySelectorAll("div[uib-datepicker-popup-wrap]");
Array.prototype.forEach.call(elements, function(node) {
node.parentNode.removeChild(node);
});
Plunker here

How to update ng-model before ng-click fires in Ionic/Angular?

Is there a known issue with Ionic (currently running 1.2.4) where the changing of values in select boxes are reflected after ng-click is fired?
In iOS the select box opens up a list on the lower part og the screen, but it's still possible to click elements outside, and that's where my problem comes into play. The click handler has the old value, since ng-click apparently fires before ng-model is updated with the newly selected value.
<select ng-options="obj as obj.name for obj in types" ng-model="filter.type">
</select>
<button ng-click="doSomething()">Button text</button>

Angular : Dropdowns, prevent ng-selected to fire ng-change

I am populating dropdowns in a forloop and wish to set the default value for each dropdown based on an expression. This seems to be working but my problem is when I set the default value via ng-selected it also fires change event which is not ideal.
I would like the change event only to be fired if the dropdown is actually changed.
<div layout="row" ng-if="layer.Styles && layer.Styles.length > 1">
<md-input-container class="md-icon-float md-block layer-style">
<md-select ng-change="vm.changeLayerStyle(layer,selectedStyle)" ng-model="selectedStyle" ng-model-options="{trackBy: '$value.Name'}" aria-label="Change Layer Style">
<md-option ng-repeat="style in layer.Styles" ng-value="style" ng-selected="style.IsDefault == true">
{{style.DisplayName}}
</md-option>
</md-select>
</md-input-container>
</div>
Using angular material for the dropdown
Repeating over option elements have a history of giving people problems. Normally i'd tell you to use ng-options on the select instead, but since you specifically need to use some material components, that is not an option.
I know it's not the prettiest solution, but you could solve the problem by keeping a copy of the last value and compare it to the current one, once the change event is fired. If that value has not changed, then ignore the event. This might need some extra tweaking since setting the layer.Styles will probably just trigger a lot of updates.
Since you didn't give us a plunker to play with, i can only suggest you play around with ng-model-options (which you are already using to control track-by) the updateOn property and setting it to something that won't be triggered by you setting the selected property. The value blur comes to mind here.

ng-change in a checkbox fired more than one time, because an ng-click over it

As a code is better than 1000 words, I've created a plunker in order to show my problem:
http://bit.ly/1uiR2wy
Given the specific DOM element, thing is that I have an input checkbox with an ng-change, I want to add an ng-click to the li that wraps it in order to be able to click in the whole area.
This new ng-click makes the method in the ng-change to happens twice. And is even worse for an SPAN DESCRIPTION 2 that is happening 3 times.
<li class="odd" ng-click="changeToggleModel($event)">
<span class="overcomeDescription ellipsis-overflow">span description</span>
<label>
<span>SPAN DESCRIPTION 2</span>
<input type="checkbox" ng-change="toggleSelection($event)" ng-model="isSelected">
</label>
</li>
I've tried with stopPropagation and it seems that it doesn't solve the issue.
Any ideas about it?
If you check the plunker and open the console you'll see the issue perfectly.
Thanks in advance to everyone
You need to stop event propagation on label level. Try this:
<label ng-click="$event.stopPropagation()" ...>
Demo: http://plnkr.co/edit/AjD9GlA3zjxABix6hegg?p=preview
The reason why it happens is that the label (connected to corresponding checkbox) sort of generates one more click event in order to pass click to the input. This click event causes described strange issues, because it still bubbles like normal event (well it is normal event), and hence is detected by ngClick directives.
Late to the party but encountered the same issue- it seems like AngularJS propagates the click event separately and explicitly. Instead of stopping propagation on the label, you can catch it on the input explicitly:
<input
type="checkbox"
ng-click="$event.stopPropagation()"
ng-change="toggleSelection($event)"
ng-model="isSelected"
>

Angular not selecting radio button from model

I'm working on system where I have an ng-repeat populating from an array of elements, with a radio buttons setting a property. When it loads in, none of the radio buttons are selected, but when I select any of the radio buttons, it binds to the model appropriately. It works in a single format without the outer ng-repeat, so I'm not sure why it refuses to select the radio button from the model.
<div ng-repeat="selectedTag in selectedGroup.tags track by $index" ng-controller="ThemesEdit_TagStylesCtrl">
<div class="type-select">
<label ng-repeat="styleGroup in styleGroups.list" ng-hide="styleGroup.name == 'Settings'">
<input type="radio" name="tagType" ng-model="selectedTag.styleGroupId" ng-value="styleGroup.styleGroupId"/> <span>{{styleGroup.name}}</span>
</label>
</div>
<div ng-include src="another_page"></div>
<div class="clear-float"></div>
<p tag-example="selectedTag" data-style-group="styleGroup"></p>
</div>
I can see that the $parent.selectedTag.styleGroupId comes through on each selectedTag, and it triggers the options in the template that is brought in with ng-include, so I know that is pretty close to working properly. The only remaining issue seems to be that it doesn't automatically select a radio button with a defined ng-model.
I'm fairly new to angular, so it could be something completely obvious, but I was hoping someone could light my way. Thank you for any and all help!
Edit: Updated with two suggestions below. Still no joy, but thought I'd edit the code to the most current iteration.
I would say the solution is ng-value="styleGroup.styleGroupId", documentation here.
I feel pretty dumb - it was something simple that I overlooked. With a single instance, publishing with the name set in <input type="radio" name="tagType" ng-model="selectedTag.styleGroupId" ng-value="styleGroup.styleGroupId"/> <span>{{styleGroup.name}}</span>" worked fine. Once I stuffed it in an ng-repeat, it was publishing under the same name="tagType" and overwriting the selection. Sure enough, when I scrolled to the bottom of my page, the last set of radio buttons were checked appropriately.
Checking the docs, the name is optional, and removing it allowed all the radio button sets to populate properly. I haven't seen any ill effects on anything else - is there anything I should be watching for?
Thanks for the help/thoughts, everyone!
I think you should use ng-model="selectedTag.styleGroupId". selectedTag shouldn't be overwritten by your inner ng-repeat.
UPDATE:
Have a look at this SO answer ng-value needs to be set true.

Resources