Get value on click from Angular UI Rating Directive - angularjs

Using this Code here: plunkr
How would I write the value on click to the console? It seems as though this will only work in a form submit environment, but I'm hoping I'm wrong.
Note that the rating element is converted into several i elements in a span, and each i has an ng-click applied to it already.
To summarize - When I select a star, spit out the value selected to the console.

Rating supports ng-click:
<rating value="rate" max="max" readonly="isReadonly"
on-hover="hoveringOver(value)" on-leave="overStar = null"
ng-click="setRating()"></rating>
In your controller, simply add:
$scope.setRating = function() {
alert($scope.rate);
};

Since clicking on an icon changes the value of the bound rating variable, you can just $watch the change of that scope variable.
eg.
$scope.$watch('rate', function(value) {
console.log(value);
});
http://plnkr.co/edit/bPmbgiI9ryZWSrn1zOfU?p=preview

Related

simple angular checkboxes

I have a T/F property called "valid" returning from an API call. I want to accurately display it as a checkbox, as well as allow the user to set/unset it. Setting or unsetting it will make a SAVE call.
{{vm.selectedQuestion}}
<md-checkbox
aria-label="Confirmed"
ng-model="vm.selectedQuestion.valid"
ng-click="vm.setReviewed()"
ng-checked="vm.selectedQuestion.valid">
Valid
</md-checkbox>
.
vm.setReviewed = function () {
vm.selectedQuestion.valid = !vm.selectedQuestion.valid;
// a bunch of other stuff
};
If the question gets loaded with value: true, then I see the checked box. If I uncheck the box, the valid property disappears from the object completely.
I know I'm doing something wrong with the ng-model and the ng-checked, but I've tried every combination I can think of.
Astonishingly, the angular docs and examples do not seem to address this simple case as far as I have found.
I would simply change it to:
{{vm.selectedQuestion}}
<md-checkbox
aria-label="Confirmed"
ng-model="vm.selectedQuestion.valid"
ng-change="vm.setReviewed()">
Valid
</md-checkbox>
with the function:
vm.setReviewed = function () {
// a bunch of other stuff depending on the value of vm.selectedQuestion.valid
};
Usually there is no need to over-complicate it (unless there is something about md-checkbox that I am not aware of). There is also no need to manually toggle the value in the ng-change (it's already changed by ng-model, and the value of vm.selectedQuestion.valid you see in the function is already after the change).
Here is the link for the docs of md-checkbox directive with a clear example:
https://material.angularjs.org/latest/api/directive/mdCheckbox
And the ng-change is as ng-change does, until angular goes v2, and then all bets are off. :)
A few notes on directives in question (with input from OP comment):
ng-click happens before the change of the ng-model and the checkbox in the element
ng-change happens after the change in the ng-model and the element
ng-checked is used only to set the checked attribute of the element if it's evaluated to truthy - should not be used alongside ng-model
Try following snippet
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.name = true;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input type="checkbox" ng-checked="name" ng-model="name">{{name}}</div>
</div>
</div>
Hope this will help you

Angular UI Bootstrap Tooltip tooltip-is-open weird behaviour

I use a tooltip directive from Angular UI Bootstrap inside one of my own directives. I want to manually toggle tooltip's visibility using tooltip-is-open attribute that Bootstrap Tooltip provides. Angular UI documentation states:
tooltip-is-open <WATCHER ICON> (Default: false) - Whether to show the tooltip.
So I assume it watches on the attribute's value. And so I want to bind a scope variable tooltipIsOpen to the attribute, hoping that changing tooltipIsOpen value in my directive's link function would toggle the tooltip visibility.
The behaviour that I get is weird.
If I bind tooltipIsOpen value as an expression: tooltip-is-open="{{ tooltipIsOpen }}", the tooltip doesn't appear at all, though I see that the DOM is updated properly (tooltip-is-open="false switches to tooltip-is-open="true" and back again to false) in reaction to mouse events.
If I bind tooltipIsOpen value as a variable: tooltip-is-open="tooltipIsOpen", the tooltip apears properly after the first mouse event, but then doesn't react to any further events, staying displayed all of the time with no way to hide it.
The working solution I found is bind tooltipIsOpen as a function call :scope.tooltipIsOpenFun = function() { return tooltipIsOpen; } and tooltip-is-open="tooltipIsOpenFun()", or as an object property: tooltip-is-open="tooltip.isOpen". Only then the tooltip works fine - shows and hides all of the time.
I suspect it's related to how AngularJS watchers work, also to the difference in how JavaScript primitives and objects are treated when assigning the values. Still I can't understand it.
Question
Can somebody explain to me step by step why the solution 1 doesn't work and 2 works only once?
Directive template (for method 2)
<div uib-tooltip="Tooltip message"
tooltip-is-open="tooltipIsOpened">
...
</div>
Directive link function
module(...).directive(..., function() {
return {
link: function(scope, elem, attr) {
/* Stop further propagation of event */
function catchEvent(event) {
event.stopPropagation();
};
function showTooltip(event) {
scope.$apply(function() {
scope.tooltipIsOpened = true;
/* Hide tooltip on any click outside the select */
angular.element(document).on('click', hideTooltip);
elem.on('click', catchEvent);
});
};
function hideTooltip() {
scope.$apply(function() {
scope.tooltipIsOpened = false;
/* Remove previously attached handlers */
angular.element(document).off('click', hideTooltip);
elem.off('click', catchEvent);
});
};
scope.tooltipIsOpened = false;
elem.on('mouseenter', showTooltip);
elem.on('mouseleave', hideTooltip);
});
1st way is incorrect because this directive expects variable name, not variable value. So correct:
<div uib-tooltip="Tooltip message" tooltip-is-open="xxx">
Or correct (you pass {{}} but then you pass not value of variable but value of variable that stores variable name):
<div ng-init="yyy='xxx'">
<div uib-tooltip="Tooltip message" tooltip-is-open="{{yyy}}">
2nd way astually works somehow:
http://plnkr.co/edit/OD07Oj2A0tfj60q2QKHe?p=preview
But it is very strange - how user supposed to click outside element without triggering mouseleave event?
The thing is that you do not need all this, just:
<button uib-tooltip="Tooltip message" trigger="mouseenter"
tooltip-is-open="tooltipIsOpened">
hello
</button>
works fine.
3rd way: if you see that 'open' does not work, but 'smth.open' works that usually means you faced 'dot issue' - you can not change parent scope variable from child scope directly, but you can change variable properties. There is a lot of examples and explanations of this issue.

ui.bootstrap popover-is-open doesn't work properly

I want not to show ui.bootstrap popover by using popover-is-open directive. For example, in template:
<button class="fa fa-link add-link"
uib-popover="popover"
popover-is-open="isOpen"> Show popover </i>
And in controller:
angular.module('demoModule').controller('PopoverDemoCtrl', function ($scope) {
$scope.isOpen = false;
});
See plunkr
I am expecting that popover should never be opened, but it opens on click on it. It seems that popover-is-open affects only first angular compiling. Any ideas?
upd: Actually, i want not to show popover only in some cases, in other cases it should be shown. For example, i have download-dialog popover and i want to show it only if size of file is greater than some limit.
The popover-is-open is only for the initial behavior, i.e. if it evaulates to true, then the popover opens instantly even without a click. If you change the value of isOpen to true in your plunkr, you see that (my example plunkr).
What you want is the popover-enable attribute:
<button class="fa fa-link add-link"
uib-popover="popover"
popover-enable="isOpen">Show popover</button>
Update for the question update:
You are free to evaluate any boolean expression in the popover-enable attribute instead of the static isOpen which always evaulates to false in your example.
I have created an advanced plunkr to show that:
<input type="text" ng-model="downloadSize">
<button class="fa fa-link add-link"
uib-popover="popover"
popover-enable="isOpen()">Show popover</button>
with the controller code
$scope.isOpen = function() { return $scope.downloadSize > 100; }
You have a new text box where you can enter a number to simulate the download size. When it gets > 100, the popup will be enabled.
In order to handle the open state whit the popover-is-open value you must set popover-trigger="none" or maybe popover-trigger="'none'". As it says in the docs
Using the 'none' trigger will disable the internal trigger(s), one can
then use the popover-is-open attribute exclusively to show and hide
the popover.
Use
$scope.$apply(function () {
$scope.isOpen = false;
});
method for applying this property

Forms-angular, how a custom directive field can affect the $pristine state of the full record?

Question related to forms-angular project.
Preamble
The default formInput directive of forms-angular can be override by a custom directive by specifying the form.directive property in an extended mongoose model,
var CategorySchema = new Schema({
name: String,
});
var PlansSchema = new Schema({
categories: {
type: [CategorySchema],
form: {
directive: 'plan-categories'
}
}
});
The custom plan-categories directive has a template where fields of [CategorySchema] can be edited.
What is working
Let's start with a first simple template:
<div>
<div ng-repeat="category in record.categories">
<input ng-model="category.name" />
</div>
</div>
Forms-angular can successfully detect changes in these custom plan-categories directive input fields bound to data (injected scope.record). In particular when changing the user changes the value of the above input fields, the "Save" button of the page is enabled, allowing the Save operation.
The activation of the Save button thanks to the following comparison in parent formInput's BaseCtrl scope false === $scope[$scope.topLevelFormName].$pristine (see base.js).
Not working
Now, the Save button doesn't get enabled, when changing the category.name variable with an expression or a function called by ng-click, as below:
<div>
<div ng-repeat="category in record.categories">
<input ng-model="category.name" />
<button ng-click="category.name = 'Hello'">Edit</button>
</div>
</div>
On button click, the category.name variable seems to be correctly changed, since the value in the input is changed accordingly. Unfortunately, the Save button stays disabled.
Note: I also unsuccessfully tried to pass to ng-click a method (from the scope injected in the link method of the custom directive) and setting the category.name variable in a $timeout call.
I guess the ng-model directive of the input field calls parent's (multi-ancestor?) $setDirty() method.
Question
how do I magically get $setDirty() called by forms-angular in order to enable the "Save" button
If it is not possible:
how do I access BaseCtrl scope and call $setDirty() when changing the record.categories elements?
Offhand I cannot think of a magical solution, but the decidedly non-magical way is to depend on $data.baseScope (see https://github.com/forms-angular/forms-angular/blob/master/js/controllers/base.js#L12) which saves going through lots of $parents.

AngularJS : Chrome hidden fields value don't update after page return

I have a form that is managed with AngularJS.
I use on ng-repeat dropdonw list to update a hidden field value.
Everything works fine until I use chrome and submit the code and then do a
"page return/Go back one page"
If i try to use the dropdonw list again it only updates the modal value in a print statement not the value of the hidden input.
<input type="hidden" name="postageId" value="{{intPostageId}}" ng-model="intPostageId" />{{intPostageId}}
{{intPostageId}} outside the input works, but the one inside doesn't update
Much appreciated
For some reason angular doesn't update hidden input values with ng-model. You will have to do a quite directive to get this to work.
You don't need the value binding you have ng-model will be enough.
module.directive('updateHidden', function () {
return function (scope, el, attr) {
var model = attr.ngModel;
scope.$watch(model, function (val) {
el.val(val);
});
};
});
I came across this problem myself. No idea why this happens but and an easy workaround I found for this is to just swap the hidden field for a text field with display:none
<input type="text" name="postageId" value="{{intPostageId}}" style="display:none">

Resources