How to add a line break in an Angular Foundation Popover content? - angularjs

This seems like it should be a simple problem but it's turning out to be a lot more involved that I initially thought.
I have a couple of items inside my Angular Foundation Popover directive that i would like to separate with a line break.
.div{ 'popover' => "Name: {{ user.name }} /br Age: {{ user.age }}", 'popover-trigger' => 'click' }
What is the solution to adding a line break where the /br is in this line of html?

This is quite tricky. If you are using angular-foundation (and I realy recommand to use it), you can modify the official popover template to be HTML unsafe - than you can use HTML in popovers:
JS
"use strict";
// app definition - don't forget to include angular-foundation module
angular.module("app", ["mm.foundation"]);
// just o controller, nothing special
angular
.module("app")
.controller("MainController", MainController);
function MainController() {
var vm = this;
vm.name = "John Doe"
vm.email = "john.doe#example.com"
}
// unsafe filter - this is used in the template below
angular
.module("app")
.filter("unsafe", unsafe)
function unsafe($sce) {
return function (val) {
return $sce.trustAsHtml(val);
};
};
// oficial popover template modification
angular
.module("template/popover/popover.html", [])
.run(["$templateCache", function($templateCache) {
$templateCache.put("template/popover/popover.html",
"<div class=\"joyride-tip-guide\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
" <span class=\"joyride-nub\" ng-class=\"{\n" +
" bottom: placement === 'top',\n" +
" left: placement === 'right',\n" +
" right: placement === 'left',\n" +
" top: placement === 'bottom'\n" +
" }\"></span>\n" +
" <div class=\"joyride-content-wrapper\">\n" +
" <h4 ng-bind-html=\"title | unsafe\" ng-show=\"title\"></h4>\n" +
" <p ng-bind-html=\"content | unsafe\"></p>\n" +
" </div>\n" +
"</div>\n" +
"");
}]);
HTML
<main ng-app="app" ng-controller="MainController as vm">
<div class="row">
<div class="small-12 column">
<div popover="{{vm.name + '<br />' + vm.email}}" popover-trigger="mouseenter">
<h1>Hover me!</h1>
</div>
</div>
</div>
</main>
Here you are working CodePen example.
You can also make your own directive to have both HTML safe popovers and HTML unsafe popovers - or you can use tooltip insetead which has support for HTML unsafe by default (directive tooltip-html-unsafe).

Related

AngularJS ng-change not working for Angularjs $compile

Error: $compile:ctreq
Missing Required Controller
Controller 'ngModel', required by directive 'ngChange', can't be found!
sample code
//create dynamic UI
var targetQDom = '<div id="' + item.id + '" style="width=100%;background: white;" ><div class="head" style="border-bottom-color: azure;border-bottom-style: double;"><a style="color:aliceblue"><i class="fa fa-times-circle-o fa-fw fa-2x bt-right" style="margin-top: -4px;" ng-change="removeR(' + item.id + ',' + (index + 1) + ',$event)"></i></a> <a style="color:white;" data-toggle="collapse" class="collapsed" data-target="#' + item.id + '-rule-' + (index + 1) + '" ng-change="targetqClick(' + item.od + ',' + (index + 1) + ',' + item.req + ')" >' + item.text + '</a></div></div>';
var $targetQDom = window.j$(targetQDom).appendTo('#appendRules');
$compile($targetQDom)($scope);
the above code will be there in the controller.
above code is dynamically creating HTML based on model data.
after running app I am getting the above error in console and it not creating UI.
If I user using the ng-click the above code works fine.
other issues with MAC OS Google chrome
but ng-click has issued in MAC OS google chrome drop-down change not working.
. If I try to change drop down value it's not triggered.so the target drop-down value is not changing.
I tried to replicate it and found some error on your code. check with this.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js">
</script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<div id="someid" style="float: left;">
<select id="some-condition-list" class="some-control cursor_Hand"
ng-model="selectedsome" ng-change="somechange(someindex,$event)" >
<option value="">Show All</option>
<option ng-repeat="some in somes.condtions " value="{{some.Id}}">{{some.name}}
</option>
</select>
</div>
<script>
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.count = 0;
$scope.some="Hey";
$scope.somes ={};
$scope.somes.condtions =[];
$scope.somes.condtions =[{'Id':'1', 'name':"Gayani"},{'Id':'2',
'name':"Chaminda"}];
$scope.selectedsome="HI";
$scope.someindex=1;
$scope.somechange = function(item, item1){
alert(item);
}
}]);
</script>
</body>

How to reference divs by class by index in AngularJS?

I am new to AngularJS. This is my first Plunker.
I am trying to make it so that if a user clicks on a link in a section, the value of the link appears in the results. The other two results should be cleared of their values.
I can't find any documentation on how to reference specific items in a class by index. In jQuery, I would normally do something like...
// get this index of the thing that was clicked
$this = $(this),
Idx = $BUTTONS.BigButtons.index($this),
ThisButton.eq(Idx).doSomething();
<body ng-controller="MainController as main">
<div class="title" ng-repeat="i in [1,2,3]">
<p>This is section {{i}}</p>
<ul>
<li ng-repeat="j in [1,2,3]">
section {{i}} - link {{j}}</li>
</ul>
<div class="results" ng-bind="main.results"></div>
</div>
</body>
var app = angular.module('controllerAsDemo', []);
app.controller('MainController', function() {
this.results = "Lame default";
this.displayContent = function(firstIdx, secondIdx) {
this.results = "populate section "
+ firstIdx
+ " with the number "
+ secondIdx
+ " - other two results should be empty"
;
};
});
Here is the Demo
I think you should not be looking at classes to achieve what you want. Angular repeat and various other directives give you the ability to do that.
I have touched your code a little and it works now. See below.
var app = angular.module('controllerAsDemo', []);
app.controller('MainController', function($scope) {
$scope.name = 'Cool Clicking';
$scope.results = [];
$scope.displayContent = function(firstIdx, secondIdx) {
$scope.results = [];
$scope.results[firstIdx] = "populate results "
+ firstIdx
+ " with the number "
+ secondIdx
+ " - other two results should be empty"
;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="controllerAsDemo" ng-controller="MainController as main">
<p>{{main.name}}!</p>
<!-- LOOP THROUGH A GALLERY THEME -->
<div class="title" ng-repeat="i in [1,2,3]">
<p>This is section {{i}}</p>
<ul>
<li ng-repeat="j in [1,2,3]">
section {{i}} - link {{j}}
</li>
</ul>
<div class="results" ng-bind="results[i]"></div>
</div>
</body>
That said, if you want to use jQuery in Angular then you simply can.
I will suggest you read about Angular Dom Manipulation here
Another approach can be seen in this plunkr where each item in the gallery has his result.

AngularJS ui-sref on infoWindow not working

The problem is that to click on the name of infoWindow redirection does not work with ui- sref or ng-click inside marker.content
index.html
<div ng-controller="MapCtrl">
<div id="mapPage" class="mapPageStyle left" >
<div id="mapPageContent" style="height:100%;background:#fff;">
<div id="mapContainer" ng-repeat="marker in markers">
</div>
</div>
</div>
</div>
controller_map.js (MapCtrl)
function createMarker(info) {
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.name,
icon: info.markerImage
});
var myClass = [];
marker.content = '<div id="hook" class="hook" >' +
'<div class="nameInfoWindow" ui-sref="page_center/comercio({IdBusiness: info.id })">' + info.name + '</div>' +
'<div style="text-align: center;">' +
'<div class="ec-stars-wrapper">' +
'</div>' +
'</div>' +
'</div>';
google.maps.event.addListener($scope.map, 'click', function () {
infoWindow.close();
});
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
Your example doesn't work because you need to $compile the harcoded template. Here you have a thread talking about compiling html from controller, the second answer talks about "working outside angular scope and expects angular parse the scope", he creates an object wich compiles html&angular dynamic code
AngularHelper.Compile = function ($targetDom, htmlToCompile, applicationName)
Injecting html from controller directly is not a god practice due to performance issues.
It could be better an angular ready implementation like angular maps, with angular maps plugin you could implement something like:
<ui-gmap-google-map
center='map.center'
zoom='map.zoom'
options='options'
control='map.control'>
<ui-gmap-markers idKey="'bid'" models="map.markers" coords="'self'">
<ui-gmap-windows show="show">
<div ng-controller="MapClickCtrl">
<h5 ng-non-bindable>{{title}}</h5>
<button class="button" ng-click="goTo('page')">Detail</button>
</div>
</ui-gmap-windows>
</ui-gmap-markers>
</ui-gmap-google-map>
This is a working example, the method goto() is fired in MapClickCtrl.

Create a list without ngRepeat

I would like to create a directive, that does not need ngRepeat, because there is some additional functionality on the directive, that doesn't play good with ngRrepeat.
This is my directive with ng-repeat:
<div>
<ul>
<li ng-repeat="item in items track by $index" ng-class="attrs.itemTheme" data-item="{{ item[attrs.itemId]}}">
<div ng-include="attrs.tpl"></div>
</li>
</ul>
</div>
attrs.tpl, nt-dimension is another directive, that uses the items values from ngRepeat:
<script type="text/ng-template" id="dimension-item-tpl.html">
<div nt-dimension x-attrs="item"></div>
</script>
Without ngRepeat:
<div>
<ul></ul>
</div>
Can some please give me an example, I am quit struggling with this.
Example of code:
http://jsfiddle.net/mato75/4zhLtjbw/
Not working example:
http://jsfiddle.net/mato75/ztLhpf2g/
Got to compile and append the ngIncluded template, but the problem is, that it compiles only the last one, because the digest cycle is to slow.
var el = jqElm.find('ul');
scope.attrs.list.forEach(function (vl) {
var tmp =
'<li class="' + attrs.itemTheme + '" data-item="' + vl.id + '">' +
'<div ng-include="\'' + attrs.itemTpl + '\'"></div>' +
'</li>';
scope.item = vl; // this is to slow :(
var b = $compile(tmp)(scope);
el.append(b);
});
You need to manually create an own scope for each li, so each item has its own data.
var ul = jqElm.find('ul');
scope.list.forEach(function (vl) {
var li = '<li><div ng-include="\'item-tpl2.html\'"></div></li>';
var newScope = scope.$new();
newScope.item = vl;
var cLi = $compile(li)(newScope);
ul.append(cLi);

Clicking a checkbox with ng-click does not update the model

Clicking on a checkbox and calling ng-click: the model is not updated before ng-click kicks in so the checkbox value is wrongly presented in the UI:
This works in AngularJS 1.0.7 and seems broken in Angualar 1.2-RCx.
<div ng-app="myApp" ng-controller="Ctrl">
<li ng-repeat="todo in todos">
<input type='checkbox' ng-click='onCompleteTodo(todo)' ng-model="todo.done">
{{todo.text}}
</li>
<hr>
task: {{todoText}}
<hr><h2>Wrong value</h2>
done: {{doneAfterClick}}
and controller:
angular.module('myApp', [])
.controller('Ctrl', ['$scope', function($scope) {
$scope.todos=[
{'text': "get milk",
'done': true
},
{'text': "get milk2",
'done': false
}
];
$scope.onCompleteTodo = function(todo) {
console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
$scope.doneAfterClick=todo.done;
$scope.todoText = todo.text;
};
}]);
Broken Fiddle w/ Angular 1.2 RCx
- http://jsfiddle.net/supercobra/ekD3r/
Working fidddle w/ Angular 1.0.0
- http://jsfiddle.net/supercobra/8FQNw/
How about changing
<input type='checkbox' ng-click='onCompleteTodo(todo)' ng-model="todo.done">
to
<input type='checkbox' ng-change='onCompleteTodo(todo)' ng-model="todo.done">
From docs:
Evaluate given expression when user changes the input. The expression is not evaluated when the value change is coming from the model.
Note, this directive requires ngModel to be present.
As reported in https://github.com/angular/angular.js/issues/4765, switching from ng-click to ng-change seems to fix this (I am using Angular 1.2.14)
The order in which ng-click and ng-model will be executed is ambiguous (since neither explicitly set their priority). The most stable solution to this would be to avoid using them on the same element.
Also, you probably do not want the behavior that the examples show; you want the checkbox to respond to clicks on the complete label text, not only the checkbox. Hence, the cleanest solution would be to wrap the input (with ng-model) inside a label (with ng-click):
<label ng-click="onCompleteTodo(todo)">
<input type='checkbox' ng-model="todo.done">
{{todo.text}}
</label>
Working example: http://jsfiddle.net/b3NLH/1/
Why dont you use
$watch('todo',function(.....
Or another solution would be to set the todo.done inside the ng-click callback and only use ng-click
<div ng-app="myApp" ng-controller="Ctrl">
<li ng-repeat="todo in todos">
<input type='checkbox' ng-click='onCompleteTodo(todo)'>
{{todo.text}} {{todo.done}}
and
$scope.onCompleteTodo = function(todo) {
todo.done = !todo.done; //toggle value
console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
$scope.current = todo;
}
Replacing ng-model with ng-checked works for me.
It is kind of a hack but wrapping it in a timeout seems to accomplish what you are looking for:
angular.module('myApp', [])
.controller('Ctrl', ['$scope', '$timeout', function ($scope, $timeout) {
$scope.todos = [{
'text': "get milk",
'done': true
}, {
'text': "get milk2",
'done': false
}];
$scope.onCompleteTodo = function (todo) {
$timeout(function(){
console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
$scope.doneAfterClick = todo.done;
$scope.todoText = todo.text;
});
};
}]);
The ordering between ng-model and ng-click seems to be different and it's something you probably shouldn't rely on. Instead you could do something like this:
<div ng-app="myApp" ng-controller="Ctrl">
<li ng-repeat="todo in todos">
<input type='checkbox' ng-model="todo.done" ng-click='onCompleteTodo(todo)'>
{{todo.text}} {{todo.done}}
</li>
<hr>
task: {{current.text}}
<hr>
<h2>Wrong value</h2>
done: {{current.done}}
</div>
And your script:
angular.module('myApp', [])
.controller('Ctrl', ['$scope', function($scope) {
$scope.todos=[
{'text': "get milk",
'done': true
},
{'text': "get milk2",
'done': false
}
];
$scope.current = $scope.todos[0];
$scope.onCompleteTodo = function(todo) {
console.log("onCompleteTodo -done: " + todo.done + " : " + todo.text);
//$scope.doneAfterClick=todo.done;
//$scope.todoText = todo.text;
$scope.current = todo;
};
}]);
What's different here is whenever you click a box, it sets that box as what's "current" and then display those values in the view. http://jsfiddle.net/QeR7y/
Usually this is due to another directive in-between your ng-controller
and your input that is creating a new scope. When the select writes
out it value, it will write it up to the most recent scope, so it
would write it to this scope rather than the parent that is further
away.
The best practice is to never bind directly to a variable on the scope
in an ng-model, this is also known as always including a "dot" in
your ngmodel. For a better explanation of this, check out this video
from John:
http://www.youtube.com/watch?v=DTx23w4z6Kc
Solution from: https://groups.google.com/forum/#!topic/angular/7Nd_me5YrHU
I just replaced ng-model with ng-checked and it worked for me.
This issue was when I updated my angular version from 1.2.28 to 1.4.9
Also check if your ng-change is causing any issue here. I had to remove my ng-change as-well to make it working.
.task{ng:{repeat:'task in model.tasks'}}
%input{type:'checkbox',ng:{model:'$parent.model.tasks[$index].enabled'}}

Resources