Conditional tooltip with Bootstrap 3 and angular - angularjs

So I can get tooltips to appear on field focus, but I only want them to sometimes. I want to add a manual trigger, but to say the docs are lacking would be to indicate that some exist. Here's what I've found so far (in the source)
// Default hide triggers for each show trigger
var triggerMap = {
'mouseenter': 'mouseleave',
'click': 'click',
'focus': 'blur'
};
...
/**
* This allows you to extend the set of trigger mappings available. E.g.:
*
* $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
*/
this.setTriggers = function setTriggers ( triggers ) {
angular.extend( triggerMap, triggers );
};
So, how do you write one of these triggers?

if you are still searching for a solution it might be handy to know that the tooltips only show when there is a text value, otherwise they don't actually show.
I myself use the popover directive, here is a plunker where you can edit your text. When you clear the field, the tooltip won't show.
http://plnkr.co/edit/Zdkyhc90qTZFzLEwtrVL?p=preview
<body ng-controller="MainCtrl">
<br/><br/>
<input type="text" size="100" ng-model="error"/><br/><br/>
<p class="btn btn-default"
popover="{{error}}"
popover-placement="right"
popover-trigger="mouseenter">Hover my error!</p>
</body>
And in the controller you just set the error initial value. Make sure you include 'ui.bootstrap' as a dependency for your app, else it won't work.
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope) {
$scope.error = 'Something went wrong';
});

AngularJS 1.5.7 and Bootstrap 3.3.6 support uib-tooltip-html properties on input, select and textarea elements. Unlike uib-tooltip properties, uib-tooltip-html properties support expressions. You should be able to express your conditions therein.
For example, here is a date of birth textbox with an expression that either names the field when valid OR explains the validation error:
<input id="dateOfBirth{{::vm.studentID}}"
name="dateOfBirth"
placeholder="Date of Birth"
uib-tooltip-html="myFormName.dateOfBirth.$valid ? 'Date of Birth' : myFormName.dateOfBirth.$error.required ? 'Date of Birth is required' : 'Date of Birth is not a valid date: mm/dd/yyyy'"
type="date"
class="form-control"
data-ng-model="vm.dateOfBirth"
data-ng-required="vm.editMode"
min="1920-01-01"
data-ng-max="vm.maxDateOfBirth"
tabindex="3" />
With a little more work you could explain the min and max date errors as well.

<label>
Open tooltips <span uib-tooltip="Hello!" tooltip-is-open="tooltipIsOpen" tooltip-placement="bottom">conditionally.</span>
</label>
Check the tooltip part of the API doc

we can use popover-enable property to show it conditional

This can be archived through Angular Property binding and the title property of the bootstrap element. In Bootstrap, a tooltip will only show in the DOM if some text was given for the title value. What you have to do is to bind property or method to the tooltip. Here getTooltip() should return either tooltip or empty string.
<button type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" [title]="getTooltip()">

Related

How to get the uib-popover to open or close when the focus of the input field changes

I have a input field that has the uib-popover control on it. I have followed the documentation on how to get the directive to open but I have noticed some discrepancies in the documentation as well as examples on plnker and SO questions here.
Within my hmtl I have the inputs set as follows:
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-6">
<label>Password</label><input type="{{user.inputType}}" ng-blur="user.validatePassword(user.newUser.password, user.newUser.confirmPassword)" placeholder="Enter Password" id="password" required class="form-control" ng-model="user.newUser.password" uib-popover-template="'myPopoverTemplate.html'" uib-popover-trigger="'focus'"/>
</div>
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-6">
<label>Confirm Password</label>
<input type="{{user.inputType}}" ng-keyup="user.validatePassword(user.newUser.password, user.newUser.confirmPassword)" placeholder="Confirm Password" id="confirmPassword" required class="form-control" ng-model="user.newUser.confirmPassword"/>
<span style="color: red">{{user.message}}</span>
</div>
Most examples as well as the SO questions on here are using an older library as attributes are not prefaced with uib-*.
This code/directive currently works and renders but it only work or appears when clicking in the field and then clicking in the same field to close the popover. I have tried both the focus trigger and the oustsideClick trigger. Both have the same result of not rendering or closing the popover unless clicking in the field.
versions of the frameworks used are:
angularjs 1.5.8
ui-bootstrap 1.3.3
Changing the trigger to match earlier examples were popover-trigger is used vs. uib-popover-trigger is used disables the popover
I have created a working plunker that demonstrates what is happening.
Any suggestions on what I am missing or what I need to change.
Thanks in advance
According to tooltip.js description, in order to set a custom trigger,
it needs to be specified via trigger option passed to the $tooltipProvider.options method. In your case for focus trigger it will be:
app.config(['$uibTooltipProvider', function ($uibTooltipProvider) {
$uibTooltipProvider.options({ trigger: 'focus' });
}]);
Updated plunker that shows how to trigger tooltip on focus handler.
There's a problem of your code, please modify like below:
app.js:
(function() {
var app = angular.module('app', ['ui.bootstrap']);
app.controller('main',[ '$scope', main]);
function main($scope)
{
vm = this;
vm.message = 'hello';
vm.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
}
}());
index.html
<input class="form-control" uib-popover-template="vm.dynamicPopover.templateUrl" popover-trigger="focus"/>
Actually, you can not just pass the template's id to the uib-popover-template attribute, you need to create an object to map it waited to pass.

AngularJS - unchanged data passed by ng-model is interpreted as undefined instead of the value

I'm using Angular to generate some inputs and populate them with data using ng-repeat. I also want to bind the data inside the input to a save changes button which takes parameters provided by ng-model directives. save changes button prints the passed arguments using the built-in JS arguments object. For some reason, unless I change the text inside the input box, the output is [undefined, undefined]. Once I change the text inside the input boxes, the correct output is printed. Why is that?
JSfiddle code.
HTML:
<div ng-app="myApp" ng-controller="MainCtrl">
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.men = [{
name: "jon snow",
status: "depands"
}, {
name: "rob stark",
status: "dead"
}];
$scope.save = function() {
console.log(arguments);
}
});
This is not recommended but for your specific requirement you can use ng-init to bind ng-value to your model
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name" ng-init="mname = man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status" ng-init="mstatus = man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
This wouldn't bind your changes to the original model.
Fiddle
ngModel doesn't update untill you use a key to change it, or set it from your controller. Because you are setting the field of the input using ngValue, it doesn't register to your ngModel untill you change it.
This problem is similar to how most datepickers don't work with ngModel, as they set the field with DOM-manipulation and NOT by inserting the value by "key".
You can easily fix this by using the following HTML instead:
<label>name</label><input type="text" ng-model="man.name"><br>
<label>status</label><input type="text" ng-model="man.status"><br>
I simply removed the ngValue and linked the ngModel to your "man".

In angularjs, how to bind a label that contains html to a button

I have a button whose label changes based on the email address in the input. If it's "bob#example.com" the button says "Auto Login", other wise just say "Login"
<input ng-model="user.email" id="email" />
<button id="login" data-ng-focus data-ng-model="user.loginSubmit">{{user.email === "bob#example.com" ? "<em>Auto</em> Login" : "Login"}}</button>
When I remove the html around the 'Auto' the button works fine, otherwise angular doesn't render anything
Example JSFiddle
Any ideas?
Thanks,
It's because you can not use Html strings in side expressions directly. You have to use ng-bind-html or ng-bind-html-unsafe directives.
You can use ng-show/ng-hide
<span ng-show="user.email === 'bob#example.com'"><em>Auto</em></span>Login</button>
Here is your fiddle
Inline Angular expressions and ng-bind do not allow HTML inside. I suggest to replace inline text binding with ng-bind-html directive:
<button
id="login"
data-ng-focus
ng-model="user.loginSubmit"
ng-bind-html="user.email === 'bob#example.com' ? '<em>Auto</em> Login' : 'Login'"
></button>
ng-bind-html has dependency on ngSanitize, so you'll have to add it too:
var app = angular.module('myApp', [
'my.controllers',
'ngSanitize'
]);
Updated JSFiddle.

Simple angularjs date input

I have an edit page for an event and one of my fields is a date. In some browsers it seems to act like a plain text box (IE8), however in chrome it displays "dd/mm/yyyy" and if you click on it it has some additional options for setting the date.
My issue though is on the edit page it's not populating the existing date (I imagine because it's not in the correct format?). The MVC controller returns the data in this format "2014-03-08T00:00:00" (just using basic CRUD controller actions).
<form name="form" class="form-horizontal">
<div class="control-group" ng-class="{error: form.EventDate.$invalid}">
<label class="control-label" for="EventDate">Event Date</label>
<div class="controls">
<input type="date" ng-model="item.EventDate" id="EventDate">
</div>
</div>
<div class="form-actions">
<button ng-click="save()" class="btn btn-primary">
{{action}}
</button>
Cancel
</div>
</form>
I've seen quite a few posts on using directives and watches, but that seems complicated. I would have thought there would have been a relatively simple way of formatting the model data so that it displays in the right format and works as expected. I don't mind if Chrome gives a different experience than other browsers - it's just a simple internal user website. I just don't like that it's not prepopulating the date when I edit a record.
If you want to populate the field with an initial value, then the following will work
//Controller:
$scope.myDate = new Date('2014-03-08T00:00:00');
//HTML:
<input type="date" ng-init="model=(myDate | date:'yyyy-MM-dd')" ng-model="model" />
However, I strongly recommend creating a custom date field directive.
A custom input field directive offers the following benefits:
Two-way binding between the model and the view.
For example, when you enter a valid date in the input field, it will automatically assign a javascript date to the model; and when you assign a valid javascript date as the model, it will automatically format it in the text field.
Form validation support. When you enter an invalid date, you can set an $error flag, which can be used in your view bindings (i.e. displaying an error message). Setting an error flag will also set form.$valid to false so that you can conditionally submit the form to the server.
There are three basic things to consider when implementing a custom date directive:
A parser that will parse the input text and return the model
(in this case, a javascript date).
A formatter that will format the model and display it in the text field.
Setting of an optional validation flag which can be used in the UI
for custom form validation.
Date Directive:
myApp.directive('dateField', function($filter) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModelController) {
ngModelController.$parsers.push(function(data) {
//View -> Model
var date = Date.parseExact(data,'yyyy-MM-dd');
// if the date field is not a valid date
// then set a 'date' error flag by calling $setValidity
ngModelController.$setValidity('date', date!=null);
return date == null ? undefined : date;
});
ngModelController.$formatters.push(function(data) {
//Model -> View
return $filter('date')(data, "yyyy-MM-dd");
});
}
}
});
Note: For parsing dates, this directive uses Date.js (an external library).
CSS:
.error {
color:red;
}
.error-border {
border: solid 2px red;
}
HTML:
<form name="myForm">
<input ng-class="{'error-border': myForm.myDate.$error.date}" type="date"
name="myDate" ng-model="myDate" date-field />
<span ng-show="myForm.myDate.$error.date" class="error">
Please enter a valid date!!!
</span>
<br /> Raw Date: {{myDate}}
<br /> Formatted Nicely: {{ myDate | date:'yyyy, MMMM dd'}}
<br /> Is Valid Date? {{ !myForm.myDate.$error.date}}
<br /> Is Form Valid? {{ myForm.$valid }}
</form>
Controller:
myApp.controller('ctrl', function($scope) {
$scope.myDate = new Date('2014-03-08T00:00:00');
});
Demo JS Fiddle with Date.js
Demo JS Fiddle with Moment.js

Show ? in textbox when textbox have ng-pattern for numeric validation

I need to show '?' when the value not able to read from scanner which returns me value by including '?'
Let say document has sr no as '123' but let say for some reason scanner not able to read it then it returns me as "12?" or "???" or "?23" or "1?3"
If any digit which is not readable that need to corrected by user manually for that i need to show them in to the textbox.
In our application we are using angularjs validations, which are not allowing me to show above values inside textbox as it contains '?' which is not numeric value.
Also I should enforce the numeric validation so that user can correct the above and submit to the server.
So how we achieve this functionality ?
<div ng-app ng-controller="formCtrl">
<form name="myForm" ng-submit="onSubmit()">
<input type="text" ng-model="price" name="price_field" ng-pattern="/^[0-9]{1,7}$/" required>
<span ng-show="myForm.price_field.$error.pattern">Not a valid number!</span>
<input ng-show="toggle" type="submit" value="submit"/>
<input ng-show="!toggle" type="button" ng-click="AfterProcessing()" value="After Processing"/>
<input type="button" value="Reset" ng-click="reset()"/>
<br/>
<span>Activity : {{message}}</span>
</form>
</div>
JS code
function formCtrl($scope){
$scope.price= "123";
$scope.toggle = false;
$scope.message="No Activity";
$scope.onSubmit = function(){
$scope.toggle=false;
$scope.message="onSubmit clicked...";
}
$scope.AfterProcessing = function(){
$scope.toggle=true;
$scope.price ="1?3";
$scope.message="AfterProcessing clicked...";
}
$scope.reset=function()
{
$scope.toggle=false;
$scope.price ="123";
$scope.message="Reset clicked...";
}
}
I have created sample as below.
Plz check on JsFiddle sample
-Thanks
You need to create a CSS Class that will be applied to text box. Using :before and :after pseudo css construct, you can add ? character and get desired result.
So,
1. Define a CSS Class with :before and/or :after as per your requirement
2. On the HTML, use ng-class="{'your-class': $error, 'regular-class': '$pristine'}"
Let me know if you need a code sample and a plunker. (I am at the end of the day. May be will provide some code tomorrow. )
If you can create a plnkr based on above and submit link here, more people would be able to help you. thanks.

Resources