Angular: How to get content from a custom div - angularjs

I want to get a the content from a custom div tag, I tried various ways to do it, not working well. Here is an example. The general item is to retrieve the content in the custom directive tags. and then bind them into the template. I hope some one can give me a suggestion or solution that does it, or does similar things
The html
<questions>
<qTitle> this is title</q-title>
<qContent> this is content <q-content>
</questions>
The angular js
var app = angular.module('app'[]);
app.directive('questions', function () {
return {
transclude: true;
template: "<div class='someCSSForTitle'>{{qTitle}}</div>"+
"<div class='someCSSForContent'>{{qContent}}</div>"
link:(scope, element, attrs)
scope.qTitle = element.find(qTitle).innerHTML
scope.qContent = element.find(qContent).innerHTML
}
}
});

First I'd advise you to read the AngularJS Guide. You didn't even copy-paste the structure correctly and you have javascript and even html errors.
Basic fixes:
HTML
<questions>
<q-title>this is title</q-title>
<q-content>this is content</q-content>
</questions>
Why do you mix qTitle and q-title?
As regarding JS:
app.directive('questions', function () {
return {
restrict: 'E',
replace: true,
template: "<div class='question'>{{title}}</div>", /* simplified */
link: function(scope, element, attrs) {
scope.title = "hallo";
console.log(element.html());
}
};
});
by default, restrict is set to 'A'. That means attributes. Your syntax is for elements.
replace set to true is not compulsory. However, because the browser doesn't understand your elements but does understand the content ("this is title"), it will print it.
the link function has to be a function. you had syntax errors there (same for transclude: you had something that you were not using followed by ";")
You can print the element to know the contents. If you do, you'll see that element in link is not question.
Now if you want to read the content, you can use a transclude function or create directives for each part and create the template separately. This seems simpler. Live example:
app.directive('questions', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
template: "<div class='question' ng-transclude></div>",
};
});
app.directive('qTitle', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
template: "<div class='title' ng-transclude></div>",
};
});
In this case you translude the contents to an inner div.
You can also define custom complex transclude functions in the compile phase but this doesn't seem necessary here.

Related

Angular directive rendering HTML mark up, how can I stop it?

I have an angular directive:
<some-dir text="{{characterDescription}}"></some-dir>
app.directive('someDir', function() {
"use strict";
return {
restrict: 'E',
transclude: false,
// replace: true,
template: '<p></p>',
scope: {
text: '#'
},
link: function(scope, elem) {
elem.append(scope.text);
}
};
});
The text which is passed into it looks like this:
{
characterDescription : <b>tall</b>
}
At the moment, it's rendering the HTML, so I'm seeing tall, but I want it to treat HTML as plain text, so I want to see <b>tall</b>.
Is there an angular way of accomplishing this in my directive?
elem.text(sometext)
This will not interpret the string as HTML, as you can see in the doc's.
jQuery.text() Docs
You could use
elem.text(scope.text);
Here's working fiddle: http://jsfiddle.net/1dL16fof/
And docs: http://api.jquery.com/text/#text2
EDIT beat to answer in comments.

Using Skobbler in AngularJS directive: 'Map container is already initialized.'

Using a directive to render the Skobbler leaflet:
angular.module('app.directives').directive('skm', function()
{
return {
restrict: 'E',
replace: true,
scope: false,
template: '<div></div>',
link: function(scope, element, attrs) {
var map = L.skobbler.map('skm', scope.skm);
// ....
}
}
});
This directive is used on different routes/partials in a similar way:
<skm id="skm"></skm>
Version info:
Skobbler 2.0
AngularJS 1.2.16
When moving from page 1 to page 2, no problem. However, going back to page 1:
Error: Map container is already initialized.
I've tried storing the map object and using map.remove(), which removes the error but stops the map from rendering.
FIXED: See my answer below. (Use unique ID's in each partial and grab those)
Fixed: Simply put a unique ID in each partial and grab the ID in the directive, then create the leaflet with this ID.
Partial 1:
<skm id="skm1"></skm>
Partial 2:
<skm id="skm2"></skm>
Directive:
angular.module('app.directives').directive('skm', function()
{
return {
restrict: 'E',
replace: true,
scope: false,
template: '<div></div>',
link: function(scope, element, attrs) {
var map = L.skobbler.map(attrs.id, scope.skm);
// ....
}
}
});
What didn't work:
replacing the outerHTML with original HTML on directive $destroy (directive didn't play well)
map.remove() (Skobbler didn't care)
Shouting profanities at the Skobbler library (Skobbler didn't care)
Skobblerjs is a "thin" fork of leafletjs so (most likely) the error comes from the leaflet logic and not the skobbler logic.
There are some other mentions of this error, see of any of following are of help to you:
https://groups.google.com/forum/#!topic/leaflet-js/xDNcNBAZq8o
http://forums.enyojs.com/discussion/540/leaflet-maps
If not - then include a jsfiddle or plunker example so that we're able to debug

Using directives inside directives causes binding issues

We're using Angular and we're having trouble with resolving variables in directives.
This fiddle shows our issue:
Here's the full code: http://jsfiddle.net/VX5LE/65/
//data-translate should handle the translating of the useableButton text
app.directive('window', ['translateService', function (translateService) {
return {
restrict: 'E',
transclude: true,
scope: {
useableButtons: '='},
replace: true,
template:
'<div>' +
'<button data-ng-repeat="useableButton in useableButtons" data-translate>{{useableButton}}</button>' +
'</div>'
};
}]);
I have seen some answers that solve this by:
Using a filter to translate these. - That is actually our current solution but that hinders us with different functionality.
Attaching watches in the controller. - We actually want to avoid watches in our controllers as it makes the code quite dirty if you have a lot of them.
Preferably I would like to see a solution that resides inside of the translate directive without cluttering the controllers.
You can do this by interpolating the values manually, then parsing it with the $eval function of the desired scope.
Here is the fiddle: http://jsfiddle.net/VX5LE/66/
The code of the translate-directive:
app.directive('translate', ['translateService', '$interpolate', function (translateService, $interpolate) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var pHTML = element.html();
var parsed = $interpolate(pHTML);
var translated_result = translateService.translate(scope.$eval(parsed));
element.text(translated_result);
}
}
}]);

angularjs directive with dynamic templates and string interpolation

The idea is to replace the directive element with the dynamic template which refers to interpolated strings.
If I use element.html() in my directive then the strings are interpolated fine but this leaves the original custom directive html element.
If I use element.replaceWith() then strings are not interpolated. I guess it has related to scope but can't figure out what's wrong.
Plunker: http://plnkr.co/edit/HyBP9d?p=preview
UPDATE
Found the solution. Using element.replaceWith($compile(html)(scope)); works.
Updated plunker: http://plnkr.co/edit/HyBP9d?p=preview
Not sure what objective is regarding replaceWIth. The problem is likely that when you replace an elememnt, you replace all events and data bound to it. This would include the angular scope for the element.
For demo provided could do it like this:
app.directive('status', function($compile) {
var linker = function(scope, element, attrs) {
element.contents().wrap('<h'+attrs.value+'>')
};
return {
restrict: 'E',
replace: true,
template:'<div>{{value}}</div>',
transclude: true,
link: linker,
scope: {
value: '='
}
};
});
DEMO:http://plnkr.co/edit/QDxIwE?p=preview

Binding To Element Text In AngularJS

Is it possible to bind to the text of an element without actually dropping into the link function?
<blink>Text Here or {{ controllerText() }}</blink>
// add a namespace for custom directives
angular.module('mydirectives', []);
angular.module('mydirectives').directive('blink', function() {
return {
restrict: 'E',
template: '<marquee scrollamount="100%">{{ can i do it here? }} </marquee>',
scope: {
// can i do it here?
}
};
});
So this is done with transclusion which merges the content of the original element with the template. The ng-transclude tag in the template is required to get it to work.
<blink>Bring the blink back<blink>
// add a namespace for custom directives
angular.module('mydirectives', []);
angular.module('mydirectives').directive('blink', function() {
return {
restrict: 'E',
transclude: true,
template: '<marquee scrollamount="100%" ng-transclude></marquee>'
}
});
You absolute can.
scope: {
text: '='
}
This adds a text attribute to the isolate scope that is linked to the value of the text attribute from the element.
So you need to change the html slightly to:
<blink text="fromController"></blink>
And then add that fromController attribute in the enclosing controller.
Here's a (very annoying) fiddle.

Resources