Tag Manager Variable from a parent of click element (toggle) - css-selectors

Here is the structure of the toggle:
<div data-id="thisIsTheID" class="abc">
<div class="edf">
<button value="false"></button>
</div>
</div>
The trigger only works with click >> all elements >> click classes contains edf. I tried click element matches css selector
div.abc
div.abc *
div.abc button
but none will work as trigger.
However, I want the data-id as variable in Google Tag Manager in order to differentiate between different toggles.
How do I create a trigger that works and how do I get the variable?
Here the actual code and debugger view:

Try making a custom JS variable like so:
function(){
return {{Click Element}}.parentElement.getAttribute("data-test-id");
}
It should return the value of your attribute on click.
But the classes look auto-generated. They feel like they can and will change on cache refresh or on front-end builds. I would try to use selectors like div[data-test-id] * or even div[data-test-id=isAgePolicy] *

Related

ng-class not updating inside of ng-repeat when array is changed

The code below is from a chat interface in an Angular application. The user will select the users they wish to send the message to by clicking on user bubbles which will add those users to an array selectedChatUsers
Lists out the users. Highlights the ones that are currently selected.
<div ng-repeat="user in PlayerController.chatUsers | orderBy:['type','name']"
class="chat-recipient"
ng-class="{'selected-recipient' : PlayerController.selectedChatUsers.indexOf(user) >= 0 }"
ng-click="PlayerController.selectRecipient(user)">
<div class="chat-recipient-name" ng-bind="user.name"></div>
<div class="chat-recipient-icon"></div>
</div>
Another feature of the application is the ability to click on a chat bubble from a sent message, and have the selectedChatUsers array be populated with the "to" property, which is an array of users that this message was sent to.
This functionality works, but the ng-class directive that should show those users are selected, does not function.
function chatReply(message){
/* one attempt was to try and manipulate the array rather than copy the information directly. This attempt had no more success. I'm including it here just to show that it was tried */
/****
self.selectedChatUsers.length = 0;
angular.forEach(message.to, function(recipient){
self.selectedChatUsers.push(recipient);
});
****/
/* Also tried wrapping the whole thing in $timeout and $scope.$apply, this also doesn't update the ng-class in the view */
$timeout(function() {
$scope.$apply(function(){
self.selectedChatUsers = angular.copy(message.to);
});
});
}
Suggestions on how I can make the ng-class in the view be updated when selectedChatUsers is changed?
Both class and ng-class will not work together, always apply class:
class="chat-recipient"
ng-class="{'selected-recipient' : condition }"
remove class and change it to:
ng-class="condition == true ? 'chat-recipient selected-recipient' : 'chat-recipient'"

How do I dynamically style uib-accordion-group

I have created a uib-accordion in my Angular website and can get most of the functionality I want, with dynamic content changing accordingly.
I am having trouble styling the uib-accordion-group dynamically.
<uib-accordion-group panel-class="panel-danger">
<uib-accordion-heading>
Accordion Heading 1
Is fine and colours the whole heading Red/Pink, I want to change this to panel-warning or panel-info based on other variables on the page.
<uib-accordion-group panel-class="{{getPanelColor()}}">
<uib-accordion-heading>
Accordion Heading 1
The function seems to be called correctly and is triggered correctly with ng-click elsewhere.
I appears that I cannot change the value panel-class uses dynamically. So in this instance getPanelColor() returns 'panel-danger', 'panel-info' or 'panel-warning' depending on other variables. If I print this return value out on the page in another div or whatever it changes correctly. If I refresh the page the correct colours are displayed for the changed panel-group.
Is there another way of setting the color - I don't know what the classes are for the accordion-group. I have tried changing the color of a div withing the panel, but this is a child element and does not change the color of the whole heading.
Any help much appreciated. (I'll come up with a JSFiddle if the question is not clear)
If you look at the HTML after the panel-class has changed and Angular has digested the change, you will see this line:
<div class="panel panel-danger" ... panel-class="panel-default">
That is, there is a mismatch between class and panel-class (the former has panel-danger, whereas the latter has panel-default). The uib-accordion-group directive simply does not handle the change in the wanted manner.
One workaround is to add ng-if to the whole group:
<uib-accordion-group ng-if="render" panel-class="{{getPanelColor()}}">
... and just before you want to change panel-class, remove the whole element temporarily, so that Angular re-renders it from scratch. Hopefully, the following code explains the principle:
$scope.render = true;
$scope.panelColor = 'panel-danger';
$scope.setPanelColor = function(val) {
$scope.panelColor = val;
$scope.render = false;
$timeout(function () {
$scope.render = true;
});
};
$scope.getPanelColor = function() {
return $scope.panelColor;
};
See the proposal in action: http://plnkr.co/edit/XfJiPnNi1z4F9cgIVxxw?p=preview. Press 'Clear panel color OK'.
The downside is that the removal of the element causes some flickering.
I have added another button 'Clear panel color FAIL' that shows what happens in your failing case. Here is what the HTML looks like after you press the button, notice the mismatch panel-danger vs. panel-default:
Use an interpolated expression in the class attribute, for example:
class="{{!ctrl.valid?'notValid':'valid'}}"

Detect clicks on button array with a single method

Im working in a school project, a minesweeper. Will be 20x20, so it has 400 buttons. Its there a way to add an actionEvent/actionPerformed and implement a generalized method for the whole array? Or there is an easier way?
Maybe something like that (using jQuery for convenience but you can do it with Vanilla JS too):
Your HTML:
<div id="buttonsHolder">
<button data-num=1>1</button>
<button data-num=2>2</button>
<button data-num=3>3</button>
...
<button data-num=4>4</button>
</div>
Your JavaScript:
$('#buttonsHolder').on('click', 'button', (function(evt){
var buttonNum = $(this).attr('data-num');
// Now, buttonNum variable holds the button number has clicked.
});
Of course instead of use data-num atribute you can use whatever data you need.
You are placing the buttons inside a container (i suppose). Add a actionhandler to that to capture a click. And read the 'target' variable of the event, and see if that is a button

Protractor not able to click on a repeater row

I am facing a strange behavior when testing an Angular JS application with protractor.
Considering this HTML structure , I would like to click on the inner div which is a filter.
<div ng-hide="term.selected" ng-click="selectFilter('target',term.value)" class="listItem">
<div>
<label class="ng-binding">ZECPFICO00</label>
<span class="listItemNum ng-binding">157</span>
</div>
</div>
Here is my locator :
element(by.repeater('term in facets.target | filter:ecSearchText').row(1)).click ();
When executing this code my webdriver cursor goes to the filter in the web page but and tries to click on the filter however the click does not work and therefore the filter is not applied.
1 - You don't need to specify the filters when using by.repeater it is optional
2 - Sirk is almost there, you need to continue chaining your promises, below an example of clicking on a div, you can use any by method here..
var elements = element.all(by.repeater('term in facets.target'));
elements.first().then(function (term) {
term.findElement(by.css('div')).then(function (div) {
div.click();
});
});
3- You could also do it this way:
element.all(by.repeater('term in facets.target')).get(0).click();
hmm I've never seen or used a locator that way where you have .row(1), but I am a noob so that just might be my own ignorance, however you could try something like the following:
element(by.repeater('term in facets.target | filter:ecSearchText')).then(function(rows){
rows[0].click();
});
That should click on the first row of the repeater. 'rows' would contain all the rows as an array.

How to get hold of template html in directive

I'm trying to create a simple time picker directive. http://plnkr.co/edit/VYGqhPbHf1yqXLpemGEP
When user click on input field I want to display the content of my template html as a dropdown below the input (will take care of css later) so that user can select a time from the list. I'm not sure how to get hold of the template (something like angular.element(template).show())
Thanks!
Edit: I managed to come up with this: http://plnkr.co/edit/zAplNKVfohXLbIzwjhy4?p=preview
Everything works except when I click any of the list, it does not set the correct model value.
Try the following:
Embed the the HTML for the date picker list
Hide the list from the html
If the input gets focus change the visibility.
Pseudo code:
HTML:
<ul ng-show="listVisible">
<li> .... </li>
</ul>
JavaScript
scope.listVisible = false;
element.$on('focus', function() {
scope.listVisible = true;
});
Do something similar in reverse.
I managed to get it working. I had to create a new scope for the dropdown element. http://plnkr.co/edit/zAplNKVfohXLbIzwjhy4?p=preview

Resources