I'm designing a component to help with alert messages within our application. Right now, it's designed to display either content passed in from an attribute, the block content within, or both. As an example:
{{#cos-alert message="This is the first line" displayBlock="all"}}
This is the second line
{{/cos-alert}}
would render:
This is the first line
This is the second line
My example handlebars template:
{{message}}<br/>
{{yield}}
However, sometimes the message attribute is bound to a property from the view that would cause it to be empty. We want to detect if there is block content, and if so we want to display it. If not, we want to hide the component with the isVisible property until there is content to display.
I haven't been able to find a way to detect whether or not there is block content, however. I could be missing something but after searching for a while I've found nothing. Is it possible to get the value of yield from the component view?
To check of there is a message check the message property.
To check if there is a template check the template property.
Look here.
That is probably what u need to check if there is a template:
hasTemplate: Em.computed.bool('template')
Related
Let me start with what I want:
<ellipsis>Text which can be truncated and displayed with an ellipsis</ellipsis>
or <ellipsis>{{ some.value.from.scope }}</ellipsis>
That's it. I just want to use transclusion in an AngularJS directive or component. But there's one hitch. I want it to produce this:
<div class="ellipsis" title="Transcluded contents">
Transcluded contents
</div>
Now if it gets truncated and displayed with an ellipsis then you can hover over it and still see the full text. It's the insertion of that transcluded text into an attribute that blows everything up for me. At least, that is, if I want it to work with AngularJS in the transclusion as well.
I can do it with a super simple component like so:
angular.module('coreComponents')
.component('ellipsis', {
bindings: {
content: '<'
},
template: '<div class="ellipsis" title="{{ $ctrl.content }}">{{ $ctrl.content }}</div>'
});
But then I'm not using transclusion anymore. That would have to be used like this:
<ellipsis content="'Text which can be truncated and displayed with an ellipsis'"/>
<ellipsis content="some.value.from.scope"/>
Not exactly elegant.
So I stuck with trying to do something using the transclusion function AngularJS provides but whenever I got the data it was always just the raw text, not the final value based upon what was in the surrounding scope. So, please show me how I could build a simple directive or component which would do this. Because I've tried and tried and tried without success to pull that off. What am I missing?
Don't ask me for what I've tried, the answer is every variant of $transclude().text() and $transclude($scope, (content) => { something }); I was able to imagine. I don't even have a record of them because I literally spent three hours trying different versions and none of them gave me a compiled value back which I could put into the component's scope or use $element.attr() to set the title on the element with whatever was passed in. I've read every question on here about transclusion and I didn't see any which made this work (though I did find several examples where if I substituted a value like '{{ something.in.scope }}' into them, they failed).
1: What I want to do is check if a page contains a specific class with a specific string, and if it does, send an event to Google Tag Manager.
2: I also need a macro to check if a certain element exists on a page and if it does, fire the tag above.
What I have been able to get together so far is the supposed tag:
<html>
<head></head>
<body>
...
<a class="myClass">Captured value</a>
...
</body>
</html>
My tag to be fired using JavaScript would look something like this:
<script>
var x = document.getElementsByClassName("myClass")[0].innerHTML;
if (x.match ("Captured value")) {
dataLayer.push({'event':'captured'});
}
</script>
So this tag will fire if it sees the above anchor with that specific class. Using the above code though, I keep getting errors:
Uncaught Type Error: Cannot read property 'innerHTML' of undefined(anonymous function)
#VM490:2InjectedScript._evaluateOn
#VM479:883InjectedScript._evaluateAndWrap
#VM479:816InjectedScript.evaluate
#VM479:682
How would I write a cleaner code to not generate an error if the class doesn't exist?
Regarding number two, how would I write a function with a return statement? I just can't figure this one out. I have tried something along the lines of:
function () {
var t = document.getElementsByClassName("myClass")[0].innerHTML;
var y = dataLayer.push({'event':'trigger'})
if (t.match ("Captured value")) {
return y;
}
I want to use a macro to check if the class exists on a page with the correct value, which in turn I can use as a trigger to fire the first tag. To use macros in GTM, I need to return a value. I just can't figure out how to check for the class value and have my tag fire upon its validation.
Another way to go is of course to write a custom HTML tag to fire on all pages and have the JavaScript look for, validate and send the event. I currently do not possess the JavaScript aptitude to figure out how that would look though.
Any suggestions are highly appreciated.
With your second block of code, I would first make it a self-invoking function
<script>
(function(){
...
}()
</script>
that checkes for the presence of the class in question and also checks for the required text. Use 'indexOf' rather than 'matches' (so you do not need to deal with regex). If those two conditions are true, then push your event to the dataLayer. Fire this tag when event equals gtm.dom, along with any other conditions you think should apply, and that should do it.
Google Tag Manager has a perfectly usable DOM element variable for this. Go to variables (assuming GTM v2), "new", "DOM Element", Selection Method "CSS selector", selector ".myClass" (from your example).
Set up a trigger "page view", trigger type "DOM ready", fire on "yourDOMelement eq. "Captured value".
Unless I misunderstand your needs you should not havbe to write any custom javascript.
My approach was all backwards. I attempted to use a JavaScript solution while I could just use a custom JS inside of Tag Manager to check for a defined value and fire a trigger if it resolved to true.
The methodology I was thinking about was about right I guess, but the way about doing it was over complicating things.
What I did was add a custom JavaScript macro named cjs.return class (using v1 for this said container) and added the following code:
function (){
x = document.getElementsByClassName("myClass")[0].innerHTML;
return x;
}
This function returned either undefined or "Captured value" depending on if it was the right page or not. I then set up a new rule to trigger my tag if:
event equals gtm.dom
cjs.return class equals Captured value
This new rule triggered my tag, which in turn could send the data on the specific set of pages I wanted it to fire on.
Thanks to both Eike and nyuen for answering to give me a clearer picture of what I did wrong.
I'm using angular-xeditable, here is my editable element:
<div class="like-pre" editable-textarea="question.answer" e-rows="10" e-cols="40" onbeforesave="validateFaq($data, 'answer')" ng-bind-html="question.answer"></div>
In controller, I use $sce.trustAsHtml to make question.answer appear as regular HTML instead of raw text. HTML can contain iframe (for youtube videos) or img elements. It works.
Problem is that after I change anything in question.answer through the editable element, IFRAME elements disappears complately. IMG elements still appears correctly after edition.
Anyone have idea whats wrong ?
Found solution. Problem was that xeditable only updates model data. After model is updated, it update editable div element through angulars bindings. Iframe was not shown, because new model content was not signed as trusted.
I had tried pass question.answer variable through $sce.trustAsHtml in onaftersave, but it didnt do anything. Thats because trustAsHtml didnt changed anything, I suppose it just marked it as trusted (dont know how it works internally).
Solution was adding empty space like this:
$sce.trustAsHtml(newQuestion.answer + ' ');
So angular finds that model has been changed and reloads editabel div with new - trusted as html - content.
I am trying to capture HTML text value using jQuery in custom script of DTM data element.
See the scenario:
Below is the snippet of code on the page:
<div class="site-categories">
<ul>
<li class="mobile-tablets main">
Mobiles & Tablets
Computers
Electronics
and so on.
So basically the ask is to capture the inner HTML text of anchor tag i.e. 'Mobiles & Tablets' or 'Computers' or 'Electronics', depending upon on what link, user clicks.
To achieve this, in the event based rule section, I have set Condition as the tag to fire when class (under div tag) equals 'site-categories' and enabled bubbling on child elements (so as to cover everything under this to fire omniture tag). And then assigning the value of data element in any evar variable.
In the data element section, after selecting the custom script option, I am writing this code:
var value = $('this').html();
return value;
or
var value = jQuery('this').html();
return value;
But this is not working. I even tried using this:
var value;
_satellite.setVar('value', jQuery('this').html());
return value;
But this also didn't worked. Can I have a solution for this ? I want this to be dynamic as in, depending upon which section user is clicking on the page, the data element should capture the inner HTML text of that particular anchor tag.
Not sure where I am going wrong.
If there is any other solution that exist for this, please let me know. That would be a great help.
Thanks in advance,
Adi
Couple of notes:
Firstly on a sidenote, in your jQuery code, this should not be wrapped in quotes. You should be passing an object reference to the jQuery wrapper. Wrapping it in quotes makes it look for an html element called "this" (e.g. <this>foobar</this>) which is not right.
As to your issue.. not sure how you have setup your rule but basically what you want to do is grab the value and put it into a data element, and then reference the data element when you set the Adobe Analytics variable. So it looks like you were on the right track, and BrettAHale's answer is on the right track too, but to put it all together:
In your rule, add a condition with criteria Data > Custom. Then click "add criteria" and in the codebox, enter in:
_satellite.setVar('linkText', jQuery(this).text());
return true;
This will set a data element named "linkText", and you return true to make sure the condition is always true. You can use "value" as the name but you should use something more descriptive so you can more easily remember it's purpose later (I used "linkText").
Then, in your Adobe Analytics section of the rule, go to the eVars section and select the eVar you want to set. Then for the "set as" value, enter in %linkText%. This is a reference to the data element you just set in the rule. Don't worry if DTM shows a tooltip saying not found or w/e; it only shows/searches for known data elements you set in the interface, not on-the-fly in rules. Click the "save evar" button and you should see e.g. eVar3="%linkText%" listed (but for whatever eVar you chose).
Save and then test/publish the rule.
In the analytics tool section or your rule, set the eVar using the following, not a data element.
%this.text%
Your evar box will show something like this. eVarX="%this.text%"
I bounced into a problem when I was trying to create a title on the first view I created within my application.
At first, i hopped over all the push actions I had within my application and applied after this create.view screen a title as refered in the code under here
this.StembureauView = Ext.create('UtrechtStem.view.Stembureaulijst_View', {
title: 'Stembureaulijst'
});
this.getMainnav().push(this.StembureauView);
this works fine, and I seem to have no problem with it. However, the first screen, so my main view, as loaded first view, doesnt accept the title statement.
Ext.create('UtrechtStem.view.MainNav', {
fullscreen: true,
title:'stembureau zoeker'
});
if i add nicely behind the fullscreen statement a title statement, it wont accept it. (this is done outside sencha architect, cause appearantly i cant modify it within sencha artchitect) It just shows blank. I tried removing the toolbar, to see if that was the mistake, but it didnt. I tried addding manualyy outside Sench
Does anybody have a clue why it wont accept the title statement there and to see if there is a work arround?
guess your class UtrechtStem.view.MainNav is inherited from the Ext.navigation.View. If yes, you can not set its title direct. Instead it borrow the active child's title.
Have a look at the doc site
Cheers, Oleg