How to use d3 v4 with Polymer 2.0 classes? - d3.js

How can d3.js (v4) be used with a Polymer 2.0 element?
Or how to use a library inside a class that already extends another class?
Trying to create a polymer d3 element to take advantage of polymer's two-way data binding and d3's syntax and functions. So that the data can be bound to a polymer property and passed to the d3.data() function?
Currently declaring d3 in the class returns undefined. Does the class need to be instantiated with d3 as a parameter? It seemed to work with Polymer 1.0. Another approach was to create a function outside of the class and call that but it's ugly. It would be nice to just use d3 inside the class.
Or is there a cleaner better way?
eg.
<script src="../../bower_components/d3/d3.js"></script>
var d3 = d3;
debugger; // hits this breakpoint first, and d3 is defined here and below
<dom-module id="my-app">
<template>
<svg id="svg"></svg>
</template>
<script>
class MyApp extends Polymer.Element {
static get is() { return 'my-app'; }
static get properties() {
return {
data: {
type: Object,
observer: '_dataChanged'
}
}
}
ready: {
var d3 = d3; // when it breaks here on the above breakpoint this is defined
debugger; // when it hits this breakpoint 2nd, d3 is undefined here and outside the class; what happened? how to scope it in?
}
_dataChanged(newValue, oldValue): {
var circle = d3.select(this.$.svg).data(newValue).enter().append(circle); //d3 undefined(! how to define?)
}
}
window.customElements.define(MyApp.is, MyApp);
</script>
</dom-module>

window.d3 is the way as you're loading the script in the global scope. You can load any external script asynchronously or synchronously.
To load it synchronously, just place the <script> tag in the <head>.
To load it asynchronously, you can add an load event listener to the <script> tag to do subsequent stuff when the load is completed.

Related

Use scrollToAnchor from ViewportScroller in angular 6

I cannot figure out how to use the function ViewportScroller.scrollToAnchor(string anchor).
First of all - how do I define an anchor in my html? I may be confusing anchors, routerlinks and fragments.
My code which is based on fragments as of now:
export class ItemsOverviewPage implements OnInit {
public items: Item[];
constructor(private route: ActivatedRoute,
private scroller: ViewportScroller) {}
public async ngOnInit(): Promise<void> {
const fragment = await this.route.fragment.first().toPromise();
if (fragment !== undefined || fragment !== null) {
this.scroller.scrollToAnchor(fragment);
}
}
}
The html is something like
<ion-card mode="md"
*ngFor="let i of items"
routerDirection="forward"
id="{{ i.title) }}">
</ion-card>
How can I refer to the id? Or should I do an <a>...</a> around whatever I want to scroll to?
I am navigating to the page like:
this.router.navigate(['/items'], { fragment: item.title });
I don't think you can do it that way.
It seems that, when you are using a ngFor, the scrolling to the anchor gets called before the DOM is finalized.
So, in your ngOnInit you can get the fragment, but won't be able to find the anchor, as the ngFor has not completed yet.
One way way to do what you want, could be to use a route parameter rather than a fragment.You can retrieve the parameter in the ngOnInit of your ItemsOverviewPageComponent and store it in a variable (e.g. _fragment), and then scroll to the anchor in the ngAfterViewInit() hook using document.getElementById(this._fragment).scrollIntoView();
Another option, could be using navigationExtras.
Even better, if you need to pass data and potentially complex objects via routes, would be to set up a service that stores the data and then inject it into the components
For more information see ActivatedRoute, NavigationExtras

ExtJs5 - overriding native method defined inside ext-all-debug.js

Suppose i want to override a function inside the native code provided by Sencha in the file ext-all-debug.js.
The function is defined inside the Ext.util.Renderable-class and has the name cacheRefEls.
The overriding should take place inside the index.html of the project to make it easier to maintain for future releases.
I have already tried out the override solutions proposed inside this thread:
Steps to overriding Sencha ExtJS standard component functionality (Ext.tree.Panel & Ext.data.TreeStore as two examples)
My index.html looks as follows:
<html>
...
<script type="text/javascript">
Ext.define('Myapp.view.Renderable', {
override: 'Ext.util.Renderable',
cacheRefEls: function(el) {
console.log("in overider method");
//my adapted version of it
}
});
</script>
...
</html>
Unfortunately after accessing the localhost:8080 over Firefox-33 it is visible from the Firebug-2-Console-log that it still uses the native version of the function.
What am i missing here?
In ExtJS 5, you need to move these methods to the privates configuration.
You should have seen the error:
Public method "cacheRefEls" conflicts with private framework method declared by Ext.util.Renderable
You can still override the private method. In your case, the solution would be:
Ext.define('Myapp.view.Renderable', {
override: 'Ext.util.Renderable',
privates: {
cacheRefEls: function(el) {
console.log("in overider method");
//my adapted version of it
}
}
});

Refresh core-ajax periodically using setTimeout and go();

I have a core-ajax component that is working fine (I see all the expected data):
<template is="auto-binding">
<core-ajax id="ds" auto url="https://server/data.json" response="{{data}}"></core-ajax>
<my-alarms alarms="{{data}}"></mu-alarms>
</template>
I'm attempting to refresh it periodically just for a proof of concept demo using the following javascript:
function f() {
$('#ds').go();
}
setTimeout(f, 1000)
This results in the following error on the line with go()
Uncaught TypeError: undefined is not a function
Here is the documentation. What am I doing wrong?
that function looks like jquery. try this.
function f() {
document.querySelector("#ds").go();
}
setTimeout(f, 1000);
not real sure about using jquery with polymer. i think it can't find elements in shadowdom like using document.querySelector can.
$ is a Map not a function in Polymer. It available only in Polymer elements and you can use it like
function f() {
$.ds.go();
}
setTimeout(f, 1000)
to access elements inside the elements shadowDOM.

load d3 with amd using dojo

Hi I'm using dojo in amd mode for my main app (html page). I would like to create a module that references d3 library to create some charts. I'm having trouble creating this module -- what I've got so far for the module (a javascript file) is this:
define(["d3"], function (d3) {
return {
setd3ChartData: function () {
//this function can be called from my main app
//but d3 isnt linked to the d3 js library
}
}
});
in my main app I've got a link to the d3 libary in a script tag
How can I get this script link into the module? I can access d3 library just fine from main app
Thanks
Pete
When you want to use D3 with Dojo you probably first want to define the D3 package in your Dojo config. For example (when using a CDN):
<script type="text/javascript">
var dojoConfig = {
async: true,
parseOnLoad: true,
packages: [{
name: "d3",
location: "http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.6/"
}]
}
</script>
Then you can use D3 by using:
require([ "d3/d3" ], function(d3) {
// Do stuff with "d3"
});
The reason you have to use "d3/d3" and not just "d3" is that the part before the / indicated the package name, in this case it's d3 (which we configured using dojoConfig).
The second part is the actual file, or in this case d3.js.
I also made a JSFiddle to show a working example of D3 loaded using the AMD loader. In that example I placed the Dojo configuration under the Fiddle options, but the setup is the same.
I also renamed the callback to d3Lib, because D3 by defaults creates the d3 global variable and now you can clearly see it's working with AMD.
If you want to use the minified version you can load "d3/d3.min".

How can I access the host of a custom element

I have a custom element which itself hosts a custom element.
<polymer-element name="flex-nonvisual">
<template>
<polymer-flex-layout></polymer-flex-layout>
</template>
</polymer-element>
Now in attached() (or some other callback) of PolymerFlexLayout I want to set the class attribute of the flex-nonvisual element.
In Javascript the code looks like this.parentNode.host.classList.add('someclass');
In Dart in attached() (after the call to super.attached()) this.parent is null
and I couldn't find any other reference to the host element.
How can I do this in Dart?
Unfortunately creation order of custom elements is not guaranteed. See the Polymer.dart discussion and the Related discussion on the Polymer discussion groups.
However as mentioned, your particular usage will break encapsulation and using CustomEvents is much more the way to go. And using Polymer this becomes very easy to implement as well.
<!-- flex_nonvisual.html file -->
<polymer-element name="flex-nonvisual">
<template>
<polymer-flex-layout on-ready="{{layoutReady}}"></polymer-flex-layout>
</template>
</polymer-element>
// polymer_flex_layout.dart file
#CustomTag('polymer-flex-layout')
class PolymerFlexLayout extends PolymerElement {
// other stuff here
void attached() {
super.attached();
dispatchEvent(new CustomEvent('ready'));
}
}
// flex_nonvisual.dart
#CustomTag('flex-nonvisual')
class FlexNonvisual extends PolymerElement {
// Other stuff here
void layoutReady(Event e, var details, Node node) {
this.classes.add('someclass');
}
}
update: Polymer >=1.0.x
shady DOM
new PolymerDom(this).parentNode;
or
domHost
short for
Polymer.dom(this).getOwnerRoot().host
full shadow DOM
(this.parentNode as ShadowRoot).host
#ChristopheHerreman and #MattB are still right about encapsulation should not be broken.
But also JS Polymer elements access the parent in their layout elements because it's still convenient in some scenarios.
This works now in PolymerDart too.
Polymer.dart <= 0.16.x
(this.parentNode as ShadowRoot).host

Resources