Adding hammer.js actions to a svg rectangle in a component Angular2 - svg

I’m working on an Angular 2 app and I have a component which inclundes a simple SVG rectangle, I’m trying to use Hammer.js library to be able to deplace and reform this SVG rectangle inside the view of my component,
therefore I’ve done those steps:
I’ve downloaded and copied 3 files to my project repository
hammer.js
hammer.min.js
hammer.min.map
I’ve added this script tag to my index head:
<script src="dev/jqueryLibs/hammer/hammer.js" type="text/javascript"></script>
And I get this error in the console:
Uncaught TypeError: Cannot read property 'addEventListener' of null
I’ve tried to import it in my component and add reference betwen the methode and the svg element, like this:
TS.File contents:
import {Component, ElementRef, AfterViewInit } from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {FORM_DIRECTIVES} from "angular2/common";
#Component({
selector: 'content',
templateUrl: 'content.component.html',
styleUrls: ['content.component.css'],
directives: [FORM_DIRECTIVES],
})
export class ContentComponent implements AfterViewInit{
static hammerInitialized = false;
constructor(private el:ElementRef)
{}
ngAfterViewInit() {
console.log('in ngAfterViewInit');
if (!ContentComponent.hammerInitialized) {
console.log('hammer not initialised');
var myElement = document.getElementById('test1');
var hammertime = new Hammer(myElement);
hammertime.on('swiperight', function(ev) {
console.log('caught swipe right');
console.log(ev);
});
ContentComponent.hammerInitialized = true;
} else {
console.log('hammer already initialised');
}
}
View file contents:
<svg class="simulation">
<rect id="test1" x="20" y="500" height="150" width="200" style="stroke:#EC9A20;stroke-width: 15; fill: none"/>
</svg>
Therefore I still am not able to move my SVG rectangle and it seems that Hammer.js is not even running according to this console message:
hammer not initialised
Anybody can tell me where is the error or what should I do?

This was resolved: The script tag of hammer declaration
must be placed after the jquery-ui library declaration in HTML file.
<script src="./dev/resources/js/jquery.js"></script>
<script src="./dev/resources/js/jquery-ui.js"></script>
<script src="./dev/jqueryLibs/jquery-1.12.1.min.js"></script>
<script src="./dev/jqueryLibs/jquery-migrate-1.2.1.min.js"></script>
<!--importer ici la js de bootstrap-->
<script src="node_modules/bootstrap/dist/js/bootstrap.js"></script>
<!--Importer ici hammer.js-->
<script src="dev/jqueryLibs/hammer/hammer.js" type="text/javascript"></script>

Related

Vue test utils cannot find child component

I am running a Vue 3.0 with Quasar library. In the application there is a component that has a child component in it. With vue test utils v 2.2.6, I cannot seem to locate the child components in order to generate events. Why?
Simplified Parent Component
<template>
<q-dialog square persistent transition-show="scale" transition-hide="scale" >
<q-card-section class="q-px-xs q-pt-none">
<ChildComponent/>
</q-card-section>
</q-dialog>
</template>
<script setup>
//imports, props, etc
</script>
<style> ... </style>
Simplified Child Component
<template>
<q-card square bordered id="new-recipient-root-element" class="new-recipient">
<q-form>...</q-form>
</q-card>
</template>
<script setup>
//imports, props, etc
</script>
<style> ... </style>
Using Jest / vue test utils like so:
wrapper = mount(ParentComponent, {
props: { ...},
global: {
plugins: [i18n],
provide: {
store: ...
},
mocks: { ... }
}
});
wrapper.vm.show();
await nextTick();
domWrapper = new DOMWrapper(document.body);
...
await domWrapper.findComponent(ChildComponent).vm.$emit('myEvent');
domWrapper.findComponent(ChildComponent) always returns nothing. If I try domWrapper.findAllComponents(), it returns an empty array.
Also noticed that I can locate all the elements, but if I click on a button, no event seems to be generated since the handlers are not called and wrapper.emitted() contains nothing.
What am I missing?

SVG element not rendering

I have a Vue Cli 3 project and I am trying to use vue-svgicon npm package I have followed all the steps in this tutorial: https://markus.oberlehner.net/blog/dynamically-loading-svg-icons-with-vue/
but when I come to inspect the expected svg element it is not displaying in the DOM despite being present in the inspector in Google Chrome - any help is appreciated.
<svg version="1.1" viewBox="0 0 16 16" class="svg-icon svg-fill"
style="height: 3em;"></svg>
I installed vue-svgicon via npm then ran the script to parse the svg into javascript. Then:
import App from './App.vue';
import router from './router';
import store from './store';
import './styles/global.scss';
import * as svgicon from 'vue-svgicon';
Vue.use(svgicon);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Then in the component I wanted to add the SVG I added the following:
<template>
<div>
<svgicon name="bin" height="3em"></svgicon>
</template>
<script>
export default {
}
</script>
<style lang="scss">
#import "../styles/home.scss";
</style>

svg <use> in Angular 2 Component seems to not work in IE11

Can anyone point me if svg <use> can work in IE 11 and how, inside of Angular 2 component?
It works fine in Chrome but does not work in IE for me.
I did include svg4everybody.js library but if I use this inside of a component template or template url, it does not work.
Please let me know what I should do. Thanks you ver much
import {Component} from '#angular/core';
#Component({
selector: 'my-app',
template: `
<h1>My First Angular 2 App</h1>
<svg viewBox="0 0 32 32" width='150' height='150' fill='pink' role='img'>
<use xlink:href="app/sprites.svg#splitup"/>
</svg>
`
})
export class AppComponent { }
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/svg4everybody/svg4everybody.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
Well, It's not related to IE11, supports it SVG or no. Problem is that, at the point, when svg4everybody.js is loaded and svg4everybody() method is called, your template isn't rendered in the DOM.
So, you will need to call svg4everybody() from component's ngOnInit method.
See this: Include External JavaScript Libraries In An Angular 2 TypeScript Project
is not supported on IE10, IE11. But inline svg will however work.
Therefore you should rely on a module to import the symbol into the dom as a standalone svg.
You can use the module: https://github.com/arkon/ng-inline-svg
With the [forceEvalStyles]="true" parameter for IE11.
This lib does not work with IE10, perhaps a reason is innerHTML not working on IE10 with SVG content.
Shims are available (I did not test the ng-inline-svg with them on IE10)
https://code.google.com/archive/p/innersvg/
https://www.npmjs.com/package/svg-innerhtml
In addition to David Gabrichidze anwser, it's possible to add svg4everyone with npm install.
npm install --save svg4everybody
Add script in angular.json
...
"scripts": ["./node_modules/svg4everybody/dist/svg4everybody.js"]
...
And then use it like this in app.component.ts:
import { Component, OnInit } from '#angular/core';
declare const svg4everybody: any;
#Component({
selector: 'app-root',
template: ''
})
export class AppComponent implements OnInit {
ngOnInit(): void {
// IE 11 external svg support
svg4everybody();
}
}

Usage of Chartjs in Angular2 App

I am currently exploring Angular2 in combination with TypeScript and I would like to include the Chartjs module in my application. In the chartjs documentation is shown how to do it using the common canvas html tag:
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {[...]});
</script>
How can I do similar things with Angular2 and TypeScript?
Thanks in advance!
You can use npm module:
angular2-chartjs
Then you can use it like this in your module:
import { ChartModule } from 'angular2-chartjs';
#NgModule({
imports: [ ChartModule ]
// ...
})
export class AppModule {
}
And in html template:
<chart [type]="type" [data]="data" [options]="options"></chart>
Don't forget to fill it with data ;)
Something like:
#Component({
selector: 'my-component',
template: `
<canvas #myChart" width="400" height="400"></canvas>
<script>
`)}
export class MyComponent {
#ViewChild('myChart') myChart;
ngAfterViewInit() {
var myChart = new Chart(this.target.nativeElement, {[...]});
}
}

SVG + Angular2 code sample does not work with interpolation

My goal is to convert code from Angular 1.3 to Angular 2 (with SVG in both cases).
I tried the following simple test code, which works in case #1 that does not involve interpolation, but does not work in case #2 (which uses interpolation), and AFAICS the only difference in the generated SVG code is the inclusion of an extra attribute in the element: class="ng-binding"
Is there a way to suppress the preceding class attribute, or is there another solution?
Btw I wasn't able to get the formatting quite right (my apologies).
Contents of HTML Web page:
<html>
<head>
<title>SVG and Angular2</title>
<script src="quickstart/dist/es6-shim.js"></script>
</head>
<body>
<!-- The app component created in svg1.es6 -->
<my-svg></my-svg>
<script>
// Rewrite the paths to load the files
System.paths = {
'angular2/*':'/quickstart/angular2/*.js', // Angular
'rtts_assert/*': '/quickstart/rtts_assert/*.js', // Runtime assertions
'svg': 'svg1.es6' // The my-svg component
};
System.import('svg');
</script>
</body>
</html>
Contents of the JS file:
import {Component, Template, bootstrap} from 'angular2/angular2';
#Component({
selector: 'my-svg'
})
#Template({
//case 1 works:
inline: '<svg><ellipse cx="100" cy="100" rx="80" ry="50" fill="red"></ellipse></svg>'
//case 2 does not work:
//inline: "<svg>{{graphics}}</svg>"
})
class MyAppComponent {
constructor() {
this.graphics = this.getGraphics();
}
getGraphics() {
// return an array of SVG elements (eventually...)
var ell1 =
'<ellipse cx="100" cy="100" rx="80" ry="50" fill="red"></ellipse>';
return ell1;
}
}
bootstrap(MyAppComponent);
SVG elements do not use the same namespace as HTML elements. When you insert SVG elements into the DOM, they need to be inserted with the correct SVG namespace.
Case 1 works because you are inserting the whole SVG, including the <svg> tags, into the HTML. The browser will automatically use the right namespace because it sees the <svg> tag and knows what to do.
Case 2 doesn't work because you are just inserting an <ellipse> tag and the browser doesn't realise it is supposed be created with the svg namespace.
If you inspect both SVGs with the browser's DOM inspector, and look at the <ellipse> tag's namespace property, you should see the difference.
You can use outerHtml of an HTML element like:
#Component({
selector: 'my-app',
template: `
<!--
<svg xmlns='http://www.w3.org/2000/svg'><ellipse cx="100" cy="100" rx="80" ry="50" fill="red"></ellipse></svg>
-->
<span [outerHTML]="graphics"></span>`
})
export class App {
constructor() {
this.graphics = this.getGraphics();
}
getGraphics() {
// return an array of SVG elements (eventually...)
var ell1 =
'<svg><ellipse cx="100" cy="100" rx="80" ry="50" fill="red"></ellipse></svg>';
return ell1;
}
}
note that the added string has to contain the <svg>...</svg>
See also How can I add a SVG graphic dynamically using javascript or jquery?

Resources