angular-ui bootstrap tooltip issue - angularjs

For some reason with the way we structured the page, the tooltip is not working.
main.html
<div class="main-navigation">
<div rt-tool-menus-"menus" selected="selectedMenus" tooltip="{{appController.displayName}}"></div>
</div>
controller.js
angular.module('abc')
.controller('abcController',.....
self.menus=[
{
heading: 'Head1',
active: false,
route: 'head1'
},
{
heading: 'Head2',
active: false,
route: 'head2'
tooltip: 'head2' // tried, doesnt work
}];
self.selectedMenus = []'
self.tooltip = appConfig.displayName; // tried not working
what would be the right approach to show tooltip with the correct header, and location?

Not sure what appConfig is (not visible in your snippet) but you have to add the text you want to show in the tooltip to an instance variable of the controller if you're using controllerAs or a $scope variable.
Please have a look at the code below or in this jsFiddle.
It's not clear what rt-tool-menus is. Is it a custom directive?
angular.module('demoApp', ['ngAnimate', 'ui.bootstrap'])
.config(function($tooltipProvider) {
$tooltipProvider.options({placement: 'bottom'});
})
.controller('mainController', function($scope){
this.displayName = 'Hello there';
});
.main-navigation {
border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.3/ui-bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.3/ui-bootstrap-tpls.js"></script>
<div ng-app="demoApp" ng-controller="mainController as mainCtrl">
<div class="main-navigation">
<div rt-tool-menus-"menus" selected="selectedMenus" tooltip="{{mainCtrl.displayName}}">Hover me to show tooltip!!!</div>
</div>
</div>

Related

How to use embed Angular UiGrid in AngularJs Component

I try to embed a ui-grid in a component, and the embedded ui-grid doesnt render
I built a Plnkr to visualize the problem.
index.html
<!doctype html>
<html ng-app="app">
<head>
<scripts> ... </script>
</head>
<body>
<div ng-controller="MainCtrl as $ctrl">
DataGrid in HTML
<div id="grid1" ui-grid="{ data: $ctrl.myData }" class="grid"></div>
<h1>Template/ Component</h1>
<hero-detail hero="$ctrl.hero" myData="$ctrl.myData"}"</hero-detail>
</div>
<script src="app.js"></script>
</body>
</html>
app.js
angular.module('app', ['ngTouch', 'ui.grid'])
.controller('MainCtrl', MainCtrl)
.component('heroDetail', {
template: `
<div>
DataGrid in Template
<div id="grid1" ui-grid="{ data: $ctrl.myData }" class="grid"></div>
<span>Name: {{$ctrl.hero.name}}</span>
</div>
`,
bindings: {
hero: '=',
myData: '='
}
});
function MainCtrl() {
this.hero = {name: 'Spawn'};
this.myData = [
{
firstName: "Cox",
lastName: "Carney",
company: "Enormo",
employed: true
},
...
];
}
Do you have an idea how to arrive at a workable solution?
Thanks for your input!
Looking at this github, all camelCase bindings in the component are translated to kabab-case in the html. So your component reference in the index.html needs to be changed from
<hero-detail hero="$ctrl.hero" myData="$ctrl.myData"></hero-detail>
into
<hero-detail hero="$ctrl.hero" my-data="$ctrl.myData"></hero-detail>
Also, a side note, you have a typo where ="$ctrl.myData"}"</hero-detail> needs to be changed to ="$ctrl.myData"></hero-detail>

Input value doesn't show inside bootstrap popover

I have a directive to display a bootstrap's popover where user can update some value. The problem is that my value is not visible as an input's value (it's bind, I can edit it). Same value is visible inside the popover just next to the input.
HTML
<div custom-popover popover-html="<div><span>{{costPrice}}</span><input type='text' ng-model='costPrice' /></div>"></div>
JS
$(elem).popover({
trigger: 'manual',
html: true,
content: () => {
var content = $compile(attr.popoverHtml)(scope);
return content;
},
placement: 'bottom'
});
Demo
It's of course some piece of whole project only, but it shows the issue. Any idea of how to make this value visible inside the input?
I think I finally figured out what's the issue.
You are using jquery for pop-over as it's not a good practice to use the jquery code with angular
Here in your case you are using angular and what ng-model does is it continuously watch on the element value and if it's change it calls the digest cycle to update all the values as per the model and vice versa.
So, as you have given the angular code to jquery content function it can cause the angular to stop watching for costPrice which you can see in popover if you implement it by ui-bootstrap popover or any other angular third party popovers then you can see the effects. Here is the code for that,
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="PopoverDemoCtrl">
<button style="margin:70px;" uib-popover-template="dynamicPopover.templateUrl" popover-placement="bottom-right" popover-title="{{dynamicPopover.title}}"
type="button" class="btn btn-default">Popover With Template</button>
<script type="text/ng-template" id="myPopoverTemplate.html">
<div>{{dynamicPopover.content}}</div>
<div class="form-group">
<label>Popup Title:</label>
<input type="text" ng-model="dynamicPopover.content" class="form-control">
</div>
</script>
<script>
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope, $sce) {
$scope.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
});
</script>
</div>
</body>
</html>
So as I said you gave the html with angular code to jquery to handle it and jquery cant handle the angular code so you get the error.
Hopefully this will help :)

Is it possible to route using HTML tag <button>?

I know how to do Angular ngRoute using <a> tag. I would like to know if it's also possible for me to use <button> tag to navigate between <ng-view>. Let's say I have the following code:
app.js & index.html
var app = angular.module('test', ['ngRoute']);
app.config(function($routeProvider) {
// mapping contacts.html to path /cnt
$routeProvider.when('/cnt', {
templateUrl: "https://www.google.co.za/", // the file to be mapped to
controller: "cctrl" // including the controller for that file
});
// mapping student.html to path /std
$routeProvider.when('/std', { // mapping url
templateUrl: "https://www.facebook.com", // the file to be mapped to
controller: "sctrl" // including the controller for that file
});
});
// creating a controller name cctrl
app.controller('cctrl', function($scope) {
});
// creating a controller name sctrl
app.controller('sctrl', function($scope) {
});
ul.zzz{
list-style: none;
width: 100%;
margin: 10px auto;
}
ul.zzz li{
float: left;
padding: 10px;
}
.mainContent ng-view{
margin: 0;
}
<html ng-app="test">
<head>
<title>Angular Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-route.js"></script>
</head>
<body>
<div>
<ul class="zzz">
<li>Student
</li>
<li>Contacts
</li>
</ul>
<br/>
</div>
<div class="mainContent">
<ng-view>
</ng-view>
</div>
</body>
</html>
the code above shows the working html page
the code below is whats running in my mind if i use button
<button name="gotoPage2" ng-click="gotoNext()">Next</button>
<script>
var app = angular.module('test',[ngRoute]);
app.config(function($routeProvider){
$routeProvider.when('button with a name gotoPage2 is click',{
templateUrl:'page2.html'
})
});
// or
app.controller('controllerName', function($scope){
$scope.gotoNext = function(){
app.config(function($routeProvider){
$routeProvider.when('button with a name gotoPage2 is click',
{templateUrl:'page2.html'}
)
});
};
});
</script>
Have you try using ng-click on the button and have a function on the controller to change the route
Html
<button ng-click="changeRoute({view})">Text</button>
Controller
...
$scope.changeRoute(view){
$location.path(view);
}
...
I usually use ui-router, i like it better then ng-route
put the button tag inside <a> it will work
<li><button>name</button>

Include external js widget in angular template

I need to include script tag which will render widget on my angularjs template.
For example I'd include this
<script type="text/javascript" src="http://100widgets.com/js_data.php?id=106"></script>
But angular will not render it.
Since the 100widgets scripts manipulate DOM and add other <script> tags to HTML file it could not work properly.
Morover some of these widgets are Flash based so the script add reference to SWF objects.
I think one possibility is to analyze the output of the request to url in src attribute (in your example http://100widgets.com/js_data.php?id=106) and trying to add the corresponding DOM manipulation and scripts to the template in which you desire the widget will appear.
Following is an example showing a page (page1) NOT WORKING (simply added the script tag as you typed) and a second page (page2) whose template has the insertions needed to show up the calendar widget.
PS: due to sandbox restriction this snippet could not work here on SO; try this CodePen version in debug mode: http://codepen.io/beaver71/pen/MyjBoP, or create your own version deployed on your local web server.
(function() {
'use strict';
angular.
module('myApp', ['ui.router']).
config(configRouteProvider).
controller('AppCtrl', AppCtrl);
function AppCtrl($location, $rootScope) {
$rootScope.$on('$stateChangeStart', onStateChangeStart);
function onStateChangeStart(event, toState, toParams, fromState, fromParams, options) {
console.log('From:', fromState.name,
'to:', toState.name);
}
}
function configRouteProvider($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/home.html'
})
.state('page1', {
url: '/pag1',
templateUrl: 'views/page1.html',
})
.state('page2', {
url: '/pag2',
templateUrl: 'views/page2.html',
});
$urlRouterProvider.otherwise('/');
}
}());
body {
margin: 0px;
}
hr {
margin: 0px;
}
.tabs {
padding: 8px;
background-color: black;
color: white;
}
.tabs a,
.tabs a:visited,
.tabs a:active,
.tabs a:hover {
color: white;
}
.my-tab {
height: 100%;
width: 100%;
position: absolute;
padding: 8px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://code.angularjs.org/1.4.0/angular.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js'></script>
</head>
<body ng-app="myApp" ng-controller="AppCtrl as app">
<div class="tabs">
Home
Page1
Page2
</div>
<hr />
<div ui-view></div>
<script id="views/home.html" type="text/ng-template">
<div class="my-tab">
<h3>Home</h3>
<p>bla bla bla</p>
</div>
</script>
<script id="views/page1.html" type="text/ng-template">
<div class="my-tab">
<h3>Page1</h3>
<p>Using script type="text/javascript"... NOT WORKING:</p>
<script type="text/javascript" src="http://100widgets.com/js_data.php?id=106"></script>
</div>
</script>
<script id="views/page2.html" type="text/ng-template">
<div class="my-tab">
<h3>Page2</h3>
<p>Workaround</p>
<!--code1-->
<div class="scriptcode">
<!--ecode1-->
<a target='_blank' href='http://100widgets.com/calendars/106-calendar.html'>
<embed align="middle" id="calendar" width="170" height="156.111111111" allowscriptaccess="always" quality="high" salign="lt" wmode="transparent" src="http://100widgets.com/js-files/postit.swf?UTCoffset=0&gid=0&text1=St Valentines is on 14th February 2012&&event_time=&rec=&rnd=0&gha=0&ghb=0&ghf=1&gbc=FFB200&gfc=040244&gtc=F9F9FF&gnu=http://mycalendar.org/widget/&fna=&ims="
type="application/x-shockwave-flash" />
</a>
<!--code2-->
</div>
<!--ecode2-->
<!--below commented cause it's not necessary -->
<!--script type="text/javascript">
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "http://100widgets.com/stat.js.php";
document.body.appendChild(js);
</script-->
</div>
</script>
</body>
Due to safety constraints, Angular does not parse <script> tags inside templates.
Then the widget you are referring to, is utilizing document.write. Document.write is unavailable once your page is done loading.
So, there seems to be no easy way out here.
However, as what you are trying to do, is something that is quite usual in add-script, krux created postscribe. A way around this issue. On my turn I created a small directive that utilizes this library.
In your template it will look something like this:
<div ps-src="http://100widgets.com/js_data.php?id=21"></div>
the directive:
function psScr($document) {
return {
restrict: 'A',
scope: {
psSrc: '#'
},
link: link
}
function link(scope, elm) {
if (typeof postscribe !== 'undefined') {
postscribe(elm[0], `<script src='${scope.psSrc}'></script>`);
} else {
// If postscibe isn't loaded, first load the needed libarary
var script = document.createElement('script');
script.src = 'https://gitcdn.xyz/repo/krux/postscribe/master/dist/postscribe.js';
script.onload = function () {
// once postscibe is in, kick it into action.
link(scope,elm);
};
document.head.appendChild(script);
}
}
}
angular.module('psSrcModule', [])
.directive('psSrc', psScr);
You can see it in action in this plunk
Not all of the widgets behave nicely in combination with postscribe though, some of them seem to display some artefacts in the html. I currently lack the time to find out who is to blame for this (100widgets or postscribe), but if you really need this, this is something that can be worked out.

AngularJs inject html element in shell from child view from markup

I'm new to angular and have been struggling to work out the best angular approach to solving this problem.
I have my shell page which has a place where I would like an element (toolbar) injected for each view.
Each view can have a slightly different toolbar (heading, buttons etc)
I would like to declare this toolbar in markup in the view so that I can bind data to it that the view is already using, and it's easier to maintain.
My understanding is that I could use a view for the injecting, but all the examples I have seen show it being populated from a template referenced in the routing file.
I have seen a directive used for updating the page title which does similar to what I want, https://github.com/apparentlymart/angularjs-viewhead but when I replicated/altered it and tried injecting complex html markup it didn't like it.
What is the recommended angular approach to solving this problem? Am I approaching the problem the wrong way?
Here is a simplified example.
http://plnkr.co/edit/n23vcBAc4tZUqBxnxcaY?p=preview
<!DOCTYPE html>
<html lang="en" data-ng-app="example">
<head>
<meta name="viewport" content="initial-scale=1" />
</head>
<body>
<a ui-sref="view1" class="md-button" >View 1</a>
<a ui-sref="view2" class="md-button" >View 2</a>
<div class="page-contents">
<div class="toolbar">This should be replaced with the toolbar from each page</div>
<div class="content-wrapper">
<div data-ui-view="page"></div>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
<script src="script.js"></script>
</body>
</html>
<div class="view1" style="background-color: yellow;">
<div class="toolbar-1" style="background-color: gray;">Toolbar 1</div>
<h2>View 1</h2>
<div>View contents</div>
</div>
<div class="view2" style="background-color: lightgreen;">
<div class="toolbar-2" style="background-color: gray;">Toolbar 2</div>
<h2>View 2</h2>
<div>View contents</div>
</div>
angular
.module('example', [
'ui.router'
]);
(function () {
'use strict';
angular
.module('example')
.config(configureRoutes);
configureRoutes.$inject = ['$stateProvider', '$urlRouterProvider'];
/* #ngInject */
function configureRoutes($stateProvider, $urlRouterProvider) {
$stateProvider
.state('view1', {
url: '/view1',
views: {
'page': {
templateUrl: 'view1.html',
}
}
})
.state('view2', {
url: '/view2',
views: {
'page': {
templateUrl: 'view2.html'
}
}
})
$urlRouterProvider.otherwise('/view1');
}
})();
The way i solved this was to create a toolbar service and had it populated from the controller. It didn't achieve my original goal of putting it in markup, but it did simplify the implementation.

Resources