Error referencing dom node in expression angular - angularjs

I am pulling xml into an angular app using x2js. I want to mix html into the content of certain elements, but this is making it difficult to pull that data back out for display. Here is an example of the xml.
<data>
<title>Some title here</title>
<desc>This is my <b>description</b></desc>
</data>
Using x2js I get this object
{"data": {
"title": "Some title here",
"desc": {
"b": "description",
"__text": "This is my"
}
}}
Since I can't use desc as is, I decided to write some code to work around it.
$scope.getText = function(csspath) {
return $($scope.rawXmlData).find(csspath);
}
Finally I bound the object to the scope and made my angular code do this.
<h1 ng-bind="data.title"></h1>
<p ng-bind-html="getText('data > title')"></p>
Angular responded by getting furious and told me this.
Error: $parse:isecdom
Referencing a DOM node in Expression
Is there a better way to achieve my goal? (besides switching to markdown since the client wants html sigh)

Not entirely sure why you are getting that error. However, by default angular will not allow you to print any html-string. You will have to "approve" your html by using $sce.trustAsHtml method.
Example
angular
.module('app', [])
.run(function($rootScope, $sce) {
$rootScope.getHtml = function(html) {
return $sce.trustAsHtml(html)
}
})
HTML
<!-- will not work -->
<p ng-bind-html="'<h1>a222sd</h1>'"></p>
<!-- will work as it is ran through $sce.trustAsHtml -->
<p ng-bind-html="getHtml('<h1>asd</h1>')"></p>
Live example http://jsbin.com/keraqazapo/edit?html,js,output.
UPDATE
Well, the error is below. ng-bind-html does only take a html-string to render. What you are doing here is that you, by jquery, return a dom element. Which is not allowed.
$scope.getText = function(csspath) {
//Returns dom element
//should return value of $sce.trustAsHtml
return $($scope.rawXmlData).find(csspath);
}

Related

Is it possible to access JSP style tag values in an angularjs html view?

Is it possible to access JSP style tag values in an angularjs html view? For example, can I get the ‘principal.firstName’ value in the browser, from the tag below? Is there an Angularjs way to do this?
<sec:authentication property="principal.firstName"/>
… or, do I need to access this serverside, and return in JSON? If I do need to access it server side, could you point me to an example, everything I have found just shows how to get principal.getName().
I’m trying to convert our jsp pages to be html.
I was able to do essentially the same thing by creating a JSON object, the values of which were these JSP variables which would be filled in by the server. This JSON object can be a separate page that is accessed by Angular using an $http.get() function.
Like this:
{'mySettings': {
'userID': <%=user.ID%>,
'firstName': '<%=user.first_name%>',
'lastName': '<%=user.last_name%>'
}}
The server will process the <%=whatever%> directives and replace them with actual data. Then your AngularJS code will issue an http.get to pull in this JSON and use it on the client.
You can create directive, that will read your attribute from sec:authentication tag and pass it on variable.
Example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleController', function() {
this.firstName = 1;
})
.directive("myProperty", function() {
return {
scope: {
val: "=myProperty"
},
link: function(scope, elem, attr) {
scope.val = attr.property;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController as vm">
<sec:authentication my-property="vm.firstName" property="principal.firstName" />{{vm.firstName}}
<div my-property="vm.name" property="john doe"></div>{{vm.name}}
</div>
</div>

TooltipHtmlUnsafe with content fetched from another div

I'm trying to show a tooltip with html content and the html I would like to be fetched from a children div which has angular markup in it.
Before I switched to ui-bootstrap I used the default bootstrap tooltip, which I created in a directive filling the content with ('.my-tooltip-content',element).html()
Now with ui-bootstrap I tried using the same directive/logic on the ui-tooltip except that now I tried setting attribute variables. The problem is, that I don't know how to get the html from my .my-tooltip-content div rendered inside the tooltip, without loosing the bindings. If I use $interpolate, I get the html of my div properly rendered, but the output is fixed then of course (doesn't update anymore), $compile I have never used before, but I thought this would be the right place for such a use, maybe I don't know how to use it, but $compile gives me an exception about circular structure.
This is a shortened version of what my app looks like:
http://plnkr.co/edit/46NsEPArtm4hph0ROlPS?p=preview
Excerpt:
<div class="hover" tooltip-html-unsafe="" tooltip-trigger="mouseenter" tooltip-placement="bottom">
<div>
<p>Hover me {{booking.name}} !</p>
<!-- about 20 more lines -->
</div>
<div class="my-tooltip-content"><!-- hidden by default -->
<p class="booker-name">{{booking.name}}</p>
<p>Does the name in this tooltip update?</p>
<!-- about 10 more complex lines -->
</div>
</div>
anApp.directive('hover', ['$compile','$interpolate', function($compile,$interpolate){
return{
restrict: 'C',
link: function(scope,element,attrs){
var html1,html2,html3;
var content = $(element).find('.my-tooltip-content');
// This works, but no binding
html1 = $interpolate(content.html())(scope);
// This I'd like to work, but I get "Can't interpolate: {{tt_content}} TypeError: Converting circular structure to JSON"
html2 = $compile(content.html())(scope);
// This brings my html into the tooltip but curlybraces are curlybraces (not compiled)
html3 = content.html();
attrs.tooltipHtmlUnsafe = html1;
}
}
}])
Is there an easy way to to get the html of .my-tooltip-content with all it's angular markup/bindings injected into the tooltip-content variable ?
PS: I know that I could squeeze all the html just directly into the tooltip-html-unsafe attribute, but I have so many lines in my real-world my-tooltip-content that this just wouldn't work (would make the tooltip-content html unreadable and unchangeable for humans).
If you need to use a child div, one solution use a function to pass the interpolated contents of the div to the tooltip. For example:
anApp.directive('hover', ['$compile','$interpolate', function($compile,$interpolate){
return{
restrict: 'C',
link: function(scope,element,attrs){
scope.myTooltip = function() {
var content = $(element).find('.tooltip-content');
return $interpolate(content.html())(scope);
};
}
}
}])
And your html would would need to be updated to use the new scope value for the tooltip:
<div class="hover" tooltip-html-unsafe="{{myTooltip()}}" tooltip-trigger="mouseenter" tooltip-placement="bottom">
Here's the updated plnkr

return a template when a user clicks on an event in Angular

I'm trying to grok the syntax for angular (just started yesterday) and the best way to achieve the following. What I'd like to do is load some compiled html and inject it into the DOM. This is a follow-up to this question: first time writing an Angular directives and returning a compiled template . Rather than call
<div my-customer></div>
I'd like to load the template dynamically based upon user interaction. Say something like:
<div ng-click="loadMyCustomer()">load customer</div><!-- should load here -->
....
arcModule.controller('MainCtrl', function($scope, $http){
$scope.sayHello(){
alert("hello here");
}
$scope.loadMyCustomer=function(){
//alert("hello");
// return the template in the mycustomer directive and place it after the current DOM element from which it is called
}
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
});
arcModule.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}}<button ng-click="sayHello()">Click to say hello.</button> Address: {{customer.address}}'
};
});
Sorry if this sounds simple but I find Angular docs a bit opaque and, if I can figure out how to return this, I'll be very happy. So, how would I return the template in the directive via the loadMyCustomer method?
For what you have highlighted it can be done without creating new directive and using the current ng-include directive.
Even if you have to do it this way
<div ng-click="showCustomer=true">...
<div my-customer ng-if="showCustomer"></div>
The advantage of ngif is that the template would not be loaded till the showCustomer is true.

Google maps for AngularJS

I am very new to AngularJS and I am trying to use https://github.com/angular-ui/angular-google-maps.
I am just trying to get the map to render on my page but I am getting an error message and I don't know what it means. Any help with understanding this error message would be appreciated.
I've created a plunk here:
github.com/twdean/plunk
Here is the Error in the browser:
Error: [$compile:multidir] Multiple directives [googleMap, markers] asking for new/isolated scope on: <google-map center="center" draggable="true" zoom="zoom" markers="markers" mark-click="true" style="height: 400px">
http://errors.angularjs.org/1.2.3/$compile/multidir?p0=googleMap&p1=markers&p2=new%2Fisolated%20scope&p3=%3Cgoogle-map%20center%3D%22center%22%20draggable%3D%22true%22%20zoom%3D%2
I suggest another alternative, ng-map.
I created a google maps angularjs directive called, ng-map, for my own project. This does not require any Javascript coding for simple functionality.
To Get Started
One. Download and include ng-map.js or ng-map.min.js
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="dist/ng-map.min.js"></script>`
Two. use map tag, and optionally, control, marker, and shape tags
<ng-map zoom="11" center="[40.74, -74.18]">
<marker position="[40.74, -74.18]" />
<shape name="circle" radius="400" center="[40.74,-74.18]" radius="4000" />
<control name="overviewMap" opened="true" />
</ng-map>`
Examples
To use it in your app, simply include 'ngMap' as dependency to your app.
var myApp = angular.module('myApp', ['ngMap']);
Hope it helps
-------------- EDIT -------------------
For those who looks for angular2 version,
there is also ng2-map https://ng2-ui.github.io/#/google-map
It seems that you're including a "markers" attribute within your google-map element.
Indeed as #Tyler Eich mentions, the docs as of Dec 5, 2013 remain outdated. Removing the marker attribute seems to make it work.
Here is how to display markers:
index.html
<div ng-controller="MapCtrl">
<google-map id="mymap"
center="center"
zoom="zoom"
draggable="true"
mark-click="false">
<markers>
<marker ng-repeat="marker in markers" coords="marker">
</marker>
</markers>
</google-map>
</div>
controller.js
var controller = module.controller('MapCtrl', function($scope) {
$scope.myMarkers = [
{
"latitude":33.22,
"longitude":35.33
},
...
];
$scope.center = {
latitude: 33.895497,
longitude: 35.480347,
};
$scope.zoom = 13;
$scope.markers = $scope.myMarkers;
$scope.fit = true;
});
I have just today had a need to implement a google map into my angular application. Since my implementation required something quite simple I decided to do this myself and create a simple directive. I will leave my source below for anyone who might find it usefull.
Create a directive
Create HTML
Optionally pass the coordinates through directive/controller if
you need.
DIRECTIVE
angular.module('ngPortalApp')
.directive('googleMap', function () {
return {
template: '<iframe width="100%" height="350" frameborder="0" style="border:0"></iframe>',
restrict: 'E',
scope: {
pbcode: '='
},
link: function postLink(scope, element) {
var mapFrame = element.find("iframe");
if (scope.pbcode) {
mapFrame.attr('src', "https://www.google.com/maps/embed?pb=" + scope.pbcode);
}
else {
mapFrame.attr('src', '');
}
}
};
});
HTML
<div class="col-lg-12">
<google-map pbcode="'!1m0!3m2!1sen!2srs!4v1445332712674!6m8!1m7!1s34JkuBgIzmIJNmpFNThuUg!2m2!1d40.75816449978445!2d-73.98911289129973!3f175.51693470959802!4f7.069842517148402!5f0.7820865974627469'"></google-map>
</div>
Thats all there is to it. Remember that the google query string is called "pb" this is the code used in all embed codes you can grab from google. You may pass this to your directive straight up or if you need to via your controller or even through the directive itself. You can set any iframe map settings in the directive within the template.
To change between Street View or Map View you just send the corresponding code whichever source you are getting them from (db, json, etc).
For the above example:
Street Code:
!1m0!3m2!1sen!2srs!4v1445332712674!6m8!1m7!1s34JkuBgIzmIJNmpFNThuUg!2m2!1d40.75816449978445!2d-73.98911289129973!3f175.51693470959802!4f7.069842517148402!5f0.7820865974627469
Map Code:
!1m18!1m12!1m3!1d755.5452773113641!2d-73.98946157079955!3d40.75804119870795!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0000000000000000%3A0x1952a6258d36ecc5!2sMcDonald's!5e0!3m2!1sen!2srs!4v1445332854795
Haven't had any issues with this as yet.
Here's a fiddle: jsFiddle
If you want to include markers you should do that in another element inside the google-maps directive.
You should do something like:
<google-maps options="someOptionsObject">
<markers cords="someArrayWithLatitudeAndLongitudeCords"></markers>
</google-maps>
For Angular2, there is angular2-google-maps. License as of 2016-05-14: MIT.

underscore template is removed from the DOM so can't be re-used

I'm trying to use a simple inline underscore.js template with backbone, and pulling the template from a <script> tag via jQuery's html() method.
The page is supposed to render multiple Recipe callouts for each returned by the Recipe Model. It works on the first thumbnail, but on the second, it seems the <script> tag has been removed from the DOM, so underscore fails to render it and bails with str is null on line 913
For the template, I have
<script type="text/html" id="user-recipe-rated-template">
<div class="user-recipe-rated">
<a class="thumb" href="<%= href %>"></a>
<p><%= title %></p>
</div>
</script>
And the backbone view looks like:
var UserRecipeView = Backbone.View.extend({
initialize : function() {
this.template = _.template($("#user-recipe-rated-template").html());
},
render : function()
{
this.el = this.template({
title: this.model.get("Title"),
href: '#'+this.model.get('UserContentId'),
image_src: this.model.get('ThumbnailSrc')
});
return this;
}
});
So, what I am seeing is that $("#user-recipe-rated-template") exists on the first thumbnail and all is well. On the second, it returns an empty array and underscore can't proceed.
I've trying memoizing the string of html and such, and that might work, but it seems there should be a cleaner way of doing this. What am I doing wrong?
(I'd like to use templates inlined as opposed to external JST for now to keep things simple - it seems nicer to have the template embedded in the page near where it will be loaded when the data comes in)

Resources