How do you dynamically add an attribute directive to a pre-existing element?
I've tried the equivalent of:
<div class="container">
<svg class="canvas"> <!-- renders up to here -->
<custom-directive>
<g class="group"> <!-- directive template -->
<rect class="body"></rect>
<g class="content"></g>
</g>
</custom-directive>
</svg>
</div>
Related
I have this code where I need to display multiple small rectangles inside a big rectangle and I need to do this entire process multiple times.
here is my data:
"data": {
"rect1": {
"a":[10,20],
"b":[35,10]
},
"rect2": {
"y":[25,10],
"z":[55,20]
}
}
This data should make two rectangles rect1 and rect2 and two rectangles inside each of them a,b and y,z respectively. each small rectangle has start position x and width of that small rectangle for example a starts at x 10 and width=20.
<ul>
<li ng-repeat="(rect,coords) in data">
<svg>
<rect x=1 y=1 width=1000 height=50 style="fill:grey;" />
<span ng-repeat="coord in coords">
<rect x={{coord[0]}} y=1 width={{coord[1]}} height=50 style="fill:blue;" />
enter code here
But this code is not working as I have added ng-repeat line between the two tags.
image of what the final result should look like
I made this image in powerpoint so ignore the background.
You were pretty close. You can't use <span> inside an SVG. But most of the rest was correct.
Also it is better to use ng-attr-x="{{value}} instead of x="{{value}}. Otherwise the SVG parser will throw errors because it doesn't understand the string "{{value}}".
Here is a working example.
var app = angular.module('myApp', [])
app.controller("AppCtrl", ["$scope", function($scope) {
$scope.data = {
"rect1": {
"a":[10,20],
"b":[35,10]
},
"rect2": {
"y":[25,10],
"z":[55,20]
}
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<ul ng-controller="AppCtrl">
<li ng-repeat="(rectName, coords) in data">
<svg id="{{rectName}}" width="100%" height="50">
<rect x="1" y="1" width="1000" height="50"
style="fill: lightgrey;" />
<rect ng-repeat="(label, coord) in coords"
ng-attr-x="{{coord[0]}}" y="1"
ng-attr-width="{{coord[1]}}" height="50"
style="fill: blue;" />
<text ng-repeat="(label, coord) in coords"
ng-attr-x="{{coord[0]}}" y="25"
style="fill: white;">{{label}}</text>
</svg>
</li>
</ul>
</div>
This is an example:
<svg>
<g ng-repeat="rect in rectList">
<rect ng-attr-fill="rect.fill"
ng-attr-x="rect.x"
ng-attr-y="rect.y"
ng-attr-width="rect.width"
ng-attr-height="rect.height"></rect>
</g>
</svg>
I want to add a <md-tooltip> to each of these rects. Can I do it somehow? I am talking about the Angular Material Tooltip specifically, not any other tooltip implementation from other libraries.
Try to wrap it in a div and apply the md-tooltip
<div ng-repeat="status in statuses">
<md-tooltip md-direction="right">
{{status.description}}
</md-tooltip>
<svg >
<rect width="300" height="100" >
</rect>
</svg>
</div>
Here is the working Sample
I'm trying to render attributes of an svg according to several properties assigned to the 'card' object instances in my 'Card' Collection. I've never used Blaze explicitly before, I'm just curious if I need to add it as a package or whether it's functionality is now built into the latest Meteor version.
<template name="card">
<div class="card svg">
<!-- <svg class="symbol" style="red" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 768">
<path d="M511.9 184l-100 200 100 200 100-200" />
</svg>
{{#each cards}}
{{> svgType this}}
{{/each}}
</div>
</template>
<template name="svgType">
{{#each svgTypes }}
<svg class="color shape quant fill">
{{> UI.dynamic template=this}}
</svg>
{{/each}}
</template>
---and then I have a list of templates in an array similar to the approach taken here: https://www.discovermeteor.com/blog/blaze-dynamic-template-includes/
So I'm making a template for the color, shape, quantity, and fill of the svg(s) rendered to each card-- then using the svgType template to render them according to my logic (ie, if (card.color === 'r', svg.color = '#12345)
Thanks in advance for any insight you can provide here...
I'm looking for a (best-practice) way to iterate through a list of elements in the scope of an angular controller and generate a div with an element specific id and append a svg to the element specific div. I'm very new to Angular...and suspect that the following attempt fails because I misunderstand Angular bindings?
What is a better way to do the following:
<div id="top_level">
<div ng-repeat="item in items">
<div id={{item.id}}>
<script type="text/javascript">
var svg_img = build_svg(args);
document.getElementById({{item.id}}).appendChild(svg_img);
</script>
</div>
</div>
</div>
Thanks!
You should place your logic inside of your controller and conditionally render as much html as necessary rather than invoking a script tag inside of an ng-repeat..
<div ng-controller="YourCtrl">
<div id="top_level">
<div ng-repeat="item in items">
<div id={{item.id}}></div>
<div ng-bind-html="$scope.buildSvg(item)">
</div>
</div>
</div>
</div>
In your angular controller, you would then add a function to build out and return the svg for you to render.
app.controller('YourCtrl', ['$scope', function ($scope) {
$scope.buildSvg = function (item) {
// add logic here.
}
});
What does your function build_svg return?
We'd need a little more information about the kind of end-result you would like to get.
But yeah, it's not really good practice to have a script element within a ng-repeat directive.
I see two solutions here:
1- Build your SVG directly within the ng-repeat
<div id="top_level">
<div ng-repeat="item in items">
<div id={{item.id}}>
<svg height="{{item.svg.attrs.height}}" width="{{item.svg.attrs.width}}">
<circle cx="50" cy="50" r="40" stroke="black" stroke- width="3" fill="red" />
</svg>
</div>
</div>
</div>
Here is a plunker of this method:
http://plnkr.co/edit/g58BUPScjKHjRLAfx6ks?p=preview
2- Create a directive to generate your SVG with some additional parameters and flexibility.
<div id="top_level">
<div ng-repeat="item in items">
<div id={{item.id}}>
<my-svg attrs="item.svg.attrs"></my-svg>
</div>
</div>
</div>
The my-svg directive would generate a SVG element with the attrs parameters.
For example, I have next html:
<header myDirective> <!-- 1 -->
...
</header>
<div menu>
...
</div>
... <!-- here are some html -->
<section>
<div myDirective> <!-- 2 -->
...
</div>
</section>
I want that myDirective with comment and myDirective with comment which are set on different DOM nodes, were combined. I mean I want that inside
directive link function I would get param "element" which would contain both of these DOM nodes. I know about property multiElement, but it works only on siblings if I understood
correctly this property. How can I get what I want? For example, I can have even such html(numbers in comments show which DOM nodes must be combined):
<header myDirective> <!-- 1 -->
<div myDirective> <!-- 2 -->
...
</div>
<div myDirective> <!-- 2 -->
...
</div>
</header>
<div myDirective> <!-- 3 -->
...
</div>
<div myDirective> <!-- 3 -->
...
</div>
<div myDirective> <!-- 1 -->
...
</div>
Smth like this is done by introducing some top-level parent directive in combine with several child directives. Child directives require parent one so they can use parent controller.
html:
<div main>
<div mydir><div><div mydir>1
</div></div></div>
<span mydir>2
</span>
Directive:
app.directive('mydir', function() {
return {
require : '^main',
link : function(scope, el, attrs, mainCtrl) {
mainCtrl.register(el);
}
};
});
http://plnkr.co/edit/znFa6lGUGmQ0bYw097zH?p=preview