How to get container dimensions before compile? - angularjs

How do I ensure that a directive gets compiled after getting dimensions of the container it is in?

Since there is no plunker/fiddle provided, this is an another guess :)
Try putting the new element into DOM before compling like this:
var newelem = '<div d3-bars bar-height="20" bar-padding="5"></div>';
newelem = angular.element(newelem);
element.append(newelem);
$compile(newelem)(scope);
That is in order to allow the new element to have width and height before get compiled.

I would guess, that you forgot to assign your scope variable. Just try $scope instead if you're in a controller.
Another possible apporach would be, to toggle a boolean variable with your button and use ng-show for your D3 code like this:
<button ng-click="showD3 = != showD3">Click me!</button>
<div d3-bars bar-height="20" bar-padding="5" ng-show="showD3"></div>

Related

pass cmsfn value to a scope variable angularjs

I'm trying to pass a variable to angularjs from cmsfn. Did anyone managed to do it already?
<div ng-controller="someController">
[#assign currentNode = cmsfn.asJCRNode(content)]
[#assign rootPageNode = cmsfn.root(currentNode, "mgnl:page")!]
<div style="display: none">{{myVar='${rootPageNode}'}}</div>
</div>
In the above code, when i try to use myVar in angular, its value is empty.
So first, reduce your FM code to single line:
[#assign rootPage = cmsfn.root(content, "mgnl:page")!]
This way, what you get back is still ContentMap and not Node which is easier to manipulate in the template.
Second, get the name of the page (if that is what you want):
${rootPage.#name}
You can find list of other special properties of content map at the bottom of this page
Now, last about the angular part, what you have in your template is just angular expression, "print statement" if you will, which will not assign variable. You need to do the assignment using $scope.myVar=... in the someController controller itself. Which means that the .js file itself needs to be freemarker template.

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'}}"

Evaluating moustache expressions after the page was initialized (dynamic binding)

I have a HTML-Document containing moustache expressions that angular-dart evaluates very well:
</head>
<body ng-cloak>
<ctrlTextElements>
<div id="stage">outside: {{ctrlTextElements.test1('three')}}</div>
</ctrlTextElements>
I want to dynamicaly add some HTML with moustache expression like so:
CtrlTextElements.addTextElement(mousePos.x, mousePos.y);
var div = dom.querySelector('#stage');
HttpRequest.getString("../path/text.html").then((r) {
div.children.add(new Element.html(r, validator: new AllowAllValidator()));
});
The content of the added text.html looks like this:
<div>inside: (not evaluated): {{ctrlTextElements.test1('three')}}</div>
That's the result in the browser:
outside: three
inside: (not evaluated):{{ctrlTextElements.test1('three')}}
How can I reevaluate the moustache expressions inside content that has been applied after the page was loaded?
The problem is that you are mixing jQuery like logic with angular logic here : manipulating the dom 'by hand' is rarely a good solution.
The problem here is that your newly added binding has not been compiled by angularjs = it has not been indexed as a directive that should be watched for and updated when scope changes.
Either you try a more angular way, for example using ng-hide or ng-repeat directive to display your content according to the controllers $scope (or another custom directive), or you try to $compile your newly added directive ( but this is bad ) : https://docs.angularjs.org/api/ng/service/$compile .
Maybe try in your controller :
$scope.$compile( div );
Not sure of the syntax though. Maybe you would need to write
<span ng-bind="..."></span>
instead of
{{ ... }}
to make it work.
#Alexhv is right. Sorry for my previous answer. I assumed it is about Polymer. Was already time for bed.
You can find a code example in my answer to this question: setInnerHtml doesn't evaluate Mustache
The pub package bwu_angular (http://pub.dartlang.org/packages/bwu_angular) contains this code as a Decorator (Directive) named bwu-safe-html

how to go from angular event to jquery selector

I know this is bad design but would like to introduce angular to a current project. I would like sayHello to be able to determine whether the element has the class 'is-a-favorite'
<div ng-click="sayHello(29, $event)" class="is-a-favorite" data-type="location" data-global-id="29" data-make-disappear="false"> </div>
$scope.sayHello=function(global_id,event){
//var selector=???
if(selector.hasClass('is-a-favorite')){
console.log("this is-a-favorite");
}
};
How would (or could) I get a reference to current DOM element to query via hasClass?
thx
The clicked element is available as $event.target, so you could check $($event.target).attr('class') or something similar.
EDIT: actually, what you'd want is to check $($event.target).hasClass('is-a-favorite')

ng-click not setting $location.path() when path is dynamic

I'm trying to use a tag like this:
<a ng-click="$location.path('/restaurant/{{restaurant._id}}')">{{restaurant.name}}</a>
However, nothing happens when I click the tag.
Oddly, if I hard-code the value there, like this:
<a ng-click="$location.path('/restaurant/512ad624b67fe1f446709331')">{{restaurant.name}}</a>
it works as expected.
Screenshot of the DOM:
Why would this be? How could I work around this?
From AngularJS ng-click not invoked with {{$index}} used, you are able to use the variable directly, without braces.
I.e.
<a ng-click="$location.path('/restaurant/' + restaurant._id)">{{restaurant.name}}</a>
Hope this helps!
$scope.doTheNeedful = function(country){
var newPath = "home/";
newPath += country;
$location.path(newPath);
}

Resources