Angular JS 2 - Error during evaluation of click - scripting

I am following a tutorial in Udemy on Angular JS and facing this problem.
My app.component.ts code
import {Component} from 'angular2/core';
import {CoursesComponent} from './courses.component'
import {AuthorComponent} from './author.component'
import {FavouriteComponent} from './favourite.component'
#Component({
selector: 'my-app',
template: `
<h1>Hello Kuttu</h1><courses></courses><authors></authors>
<fav></fav>
`,
directives: [CoursesComponent,AuthorComponent,FavouriteComponent]
})
export class AppComponent {
}
my favourite component code
import {Component} from 'angular2/core'
#Component({
selector: 'fav',
template: `
<i
class="glyphicon"
[class.glyphicon-star-empty]="!isFavourite"
[class.glyphicon-star]="isFlag"
(click)="onBClick()"
>
</i>
`
})
export class FavouriteComponent(){
isFavourite = false;
onBClick(){
this.isFavourite = !this.isFavourite;
}
}
The star is rendered in the view and when i click, i am getting the exception
EXCEPTION: Error during evaluation of "click"
angular2.dev.js:23083 EXCEPTION: Error during evaluation of "click"
BrowserDomAdapter.logError # angular2.dev.js:23083
BrowserDomAdapter.logGroup # angular2.dev.js:23094

made a stupid mistake
FavouriteComponent(){
had a () in the class name and since my editor is not something which can do compilation, i missed this error.

Related

Vue Utils invalid prop

Vue Util throws a console log error:
console.error
[Vue warn]: Invalid prop: type check failed for prop "icon". Expected Object, Array, String, got Undefined
I got a parent component in this case 'myComp' and inside I have another global component which is here Font Awesome, which is already imported. the error that I get is that prop icon is undefined, in 'myComp' prop icon doesn't exist, so I assume vue utils reads 'fa' component and looks for a prop icon in 'myComp'. All of my test pass, I just get this warning and want to get rid of it.
I Import my global components in an extra file called componentsbind.js, which already is tested and works.
import { library } from '#fortawesome/fontawesome-svg-core'
import { faUserSecret } from '#fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
library.add(faUserSecret)
my component: this is a reusable component that I am testing
<template>
<button #click="handleClick">
<template v-if="loading">
<fa :icon="faChevronRight " class="fa-spin text-xl" />
</template>
<template v-else>
<slot />
</template>
</button>
</template>
inside my component I already Imported with
<script>
import { faChevronRight } from '#fortawesome/free-solid-svg-icons'
...
my test
import { shallowMount, RouterLinkStub } from '#vue/test-utils'
import MyComp from '#/components/MyComp.vue'
let wrapper
beforeEach(() => {
wrapper = shallowMount(MyComp, {
slots: {},
stubs: {}
})
})
afterEach(() => {
wrapper.destroy()
})
describe('MyComp Test', () => {
//here are my tests...
})
So my problem was that I wasn't importing vue use composition api.
And because I return the icon on setup function it was always undefined.
so in the file where I import all my global components I just added:
import VueCompositionAPI from '#vue/composition-api'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
Vue.use(VueCompositionAPI)

Ionic Vue: VueJsPaginate not showing

I am developing an app which has a list of objects that I want to paginate. I found vuejs-paginate plugin but I can't make it work in my view.
After installing it via npm and importing in the view, its tag is in fact in the HTML skeleton of the page, but it shows nothing. No error is displayed in the console either, only this Vue warning:
[Vue warn]: Failed to resolve component: paginate
Might it be a problem with the import? Could you help me?
I attach part of my code so you can see how I've declared it.
<template>
<ion-page>
<ion-content>
<paginate
:pageCount="10"
:containerClass="'pagination'"
:clickHandler="clickCallback"
>
</paginate>
</ion-content>
</ion-page>
</template>
<script>
import {
IonContent,
IonPage,
} from "#ionic/vue";
import { defineComponent } from "vue";
import { VuejsPaginate } from "vuejs-paginate";
export default defineComponent({
name: "Gestion",
components: {
'paginate': VuejsPaginate,
},
methods: {
clickCallback: function(page) {
console.log(page)
},
});
</script>
This has also happened to me when trying to import other "external" components. Could it be a problem related to Ionic?
Thank you in advance!

Vue: How to use Directives from Libraries

Im trying to use this library: https://github.com/rigor789/vue-scrollto
But Im having trouble using it and the instructions are not very helpful to me. it says I should do this:
var Vue = require('vue');
var VueScrollTo = require('vue-scrollto');
Vue.use(VueScrollTo)
But I have no idea where to do this. So I have tried just using it like this:
<template>
<div>
<Navbar/>
<Cover/>
<button class="btn btn-primary" v-scroll-to="'#about'">Hallo</button>
<Offers/>
<AboutUs id="about"/>
<Info/>
</div>
</template>
<script>
import Navbar from '#/components/Navbar'
import Cover from '#/components/main/Cover'
import Offers from '#/components/main/Offer/Offers'
import AboutUs from '#/components/main/AboutUs'
import Info from '#/components/main/Info'
import Menu from '#/components/main/menu/Menu'
var Vue = require('vue');
var VueScrollTo = require('vue-scrollto');
Vue.use(VueScrollTo)
export default {
components: {
Navbar,
Cover,
Offers,
AboutUs,
Info,
Menu
}
}
</script>
But that doesn't work. So how do I import libraries properly so I can use the directives?
Try to use import instead of using require.
The es6 script will be transpiled to old js versions when you build the app.
<template>
<div>
<Navbar/>
<Cover/>
<button class="btn btn-primary" v-scroll-to="'#about'">Hallo</button>
<Offers/>
<AboutUs id="about"/>
<Info/>
</div>
</template>
<script>
import Navbar from '#/components/Navbar'
import Cover from '#/components/main/Cover'
import Offers from '#/components/main/Offer/Offers'
import AboutUs from '#/components/main/AboutUs'
import Info from '#/components/main/Info'
import Menu from '#/components/main/menu/Menu'
import Vue from 'vue';
import VueScrollTo from 'vue-scrollto';
Vue.use(VueScrollTo)
export default {
components: {
Navbar,
Cover,
Offers,
AboutUs,
Info,
Menu
}
}
</script>
So bacause I use Vue it did the following:
create a new file called nuxt-scroll-to.js in the plugins folder with this code:
import Vue from 'vue';
import VueScrollTo from 'vue-scrollto/vue-scrollto.js';
Vue.use(VueScrollTo)
and the in the nuxt.config.js array add this code: { src: '~/plugins/nuxt-scroll-to.js', ssr: false },

VUE 2 : Referencing VUE component inside another component's <template>. Module not found exception

i have been googling around for quite some time now to figure out WHY.. my modal component won't get recognized inside my vieworder.vue component.
I'm receiving :
ERROR in ./~/babel-loader/lib!./~/vue-loader/lib/selector.js?
type=script&index=0!./src/components/ViewOrder.vue
Module not found: Error: Can't resolve './components/Modal.vue' in
'C:\xxxxxx\xxxxxxxxx\src\components'
ViewOrder.vue - usage of modal :
<template>
<div class="col-sm-10 col-sm-offset-1" v-if="order">
<modal v-if="showModal" #close="showModal = false">
</modal>
</div>
</template>
<script>
import * as types from '../store/mutationtypes'
import { mapGetters, mapActions } from 'vuex'
import Modal from './components/Modal.vue'
export default {
name: 'ViewOrder',
components: {
'modal': Modal
}
....
Modal.vue
<template>
....
</template>
<script>
export default {
name: "modal"
}
</script>
Main.js - Reference :
....
import Modal from './components/Modal.vue'
import ViewOrder from './components/ViewOrder.vue'
....
import Modal from './components/Modal.vue'
Should be import Modal from './Modal.vue'
You're already in the components folder when inside ViewOrder.vue

Angular 2 equivalent of ng-bind-html, $sce.trustAsHTML(), and $compile?

In Angular 1.x, we could insert HTML in real-time by using the HTML tag ng-bind-html, combined with the JavaScript call $sce.trustAsHTML(). This got us 80% of th way there, but wouldn't work when Angular tags were used, such as if you inserted HTML that used ng-repeat or custom directives.
To get that to work, we could use a custom directive that called $compile.
What is the equivalent for all of this in Angular 2? We can bind using [inner-html] but this only works for very simple HTML tags such as <b>. It doesn't transform custom angular 2 directives into functioning HTML elements. (Much like Angular 1.x without the $compile step.) What is the equivalent of $compile for Angular 2?
In Angular2 you should use DynamicComponentLoader to insert some "compiled content" on the page. So for example if you want to compile next html:
<div>
<p>Common HTML tag</p>
<angular2-component>Some angular2 component</angular2-component>
</div>
then you need to create component with this html as a template (let's call it CompiledComponent) and use DynamicComponentLoader to insert this component on the page.
#Component({
selector: 'compiled-component'
})
#View({
directives: [Angular2Component],
template: `
<div>
<p>Common HTML tag</p>
<angular2-component>Angular 2 component</angular2-component>
</div>
`
})
class CompiledComponent {
}
#Component({
selector: 'app'
})
#View({
template: `
<h2>Before container</h2>
<div #container></div>
<h2>After conainer</h2>
`
})
class App {
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
loader.loadIntoLocation(CompiledComponent, elementRef, 'container');
}
}
Check out this plunker
UPD You can create component dynamically right before the loader.loadIntoLocation() call:
// ... annotations
class App {
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
// template generation
const generatedTemplate = `<b>${Math.random()}</b>`;
#Component({ selector: 'compiled-component' })
#View({ template: generatedTemplate })
class CompiledComponent {};
loader.loadIntoLocation(CompiledComponent, elementRef, 'container');
}
}
I personally don't like it, it's look like a dirty hack to me. But here is the plunker
PS Beware that at this moment angular2 is under active development. So situation can be changed at any time.
DynamicComponentLoader is deprecated, you can use ComponentResolver instead
You could use this directive, add pipes if you need additional data manipulation. It also allows for lazy loading, you don't need it in your case, but it's worth mentioning.
Directive(I found this code and made some changes, you can do that too to make it fit your taste or use it as is):
import { Component, Directive, ComponentFactory, ComponentMetadata, ComponentResolver, Input, ReflectiveInjector, ViewContainerRef } from '#angular/core';
declare var $:any;
export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {};
const decoratedCmp = Component(metadata)(cmpClass);
return resolver.resolveComponent(decoratedCmp);
}
#Directive({
selector: 'dynamic-html-outlet',
})
export class DynamicHTMLOutlet {
#Input() htmlPath: string;
#Input() cssPath: string;
constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) {
}
ngOnChanges() {
if (!this.htmlPath) return;
$('dynamic-html') && $('dynamic-html').remove();
const metadata = new ComponentMetadata({
selector: 'dynamic-html',
templateUrl: this.htmlPath +'.html',
styleUrls: [this.cssPath]
});
createComponentFactory(this.resolver, metadata)
.then(factory => {
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
this.vcRef.createComponent(factory, 0, injector, []);
});
}
}
Example how to use it:
import { Component, OnInit } from '#angular/core';
import { DynamicHTMLOutlet } from './../../directives/dynamic-html-outlet/dynamicHtmlOutlet.directive';
#Component({
selector: 'lib-home',
templateUrl: './app/content/home/home.component.html',
directives: [DynamicHTMLOutlet]
})
export class HomeComponent implements OnInit{
html: string;
css: string;
constructor() {}
ngOnInit(){
this.html = './app/content/home/home.someTemplate.html';
this.css = './app/content/home/home.component.css';
}
}
home.component.html:
<dynamic-html-outlet [htmlPath]="html" [cssPath]="css"></dynamic-html-outlet>
After reading a lot, and being close of opening a new topic I decided to answer here just to try to help to others. As I've seen there are several changes with the latest version of Angular 2. (Currently Beta9)
I'll try to share my code in order to avoid the same frustration I had...
First, in our index.html
As usual, we should have something like this:
<html>
****
<body>
<my-app>Loading...</my-app>
</body>
</html>
AppComponent (using innerHTML)
With this property you will be able to render the basic HTML, but you won't be able to do something similar to Angular 1.x as $compile through a scope:
import {Component} from 'angular2/core';
#Component({
selector: 'my-app',
template: `
<h1>Hello my Interpolated: {{title}}!</h1>
<h1 [textContent]="'Hello my Property bound: '+title+'!'"></h1>
<div [innerHTML]="htmlExample"></div>
`,
})
export class AppComponent {
public title = 'Angular 2 app';
public htmlExample = ' <div>' +
'<span [textContent]="\'Hello my Property bound: \'+title"></span>' +
'<span>Hello my Interpolated: {{title}}</span>' +
'</div>'
}
This will render the following:
Hello my Interpolated: Angular 2 app!
Hello my Property bound: Angular 2 app!
Hello my Interpolated: {{title}}
AppComponent Using DynamicComponentLoader
There is a little bug with the docs, documented in here. So if we have in mind that, my code should look now like this:
import {DynamicComponentLoader, Injector, Component, ElementRef, OnInit} from "angular2/core";
#Component({
selector: 'child-component',
template: `
<div>
<h2 [textContent]="'Hello my Property bound: '+title"></h2>
<h2>Hello my Interpolated: {{title}}</h2>
</div>
`
})
class ChildComponent {
title = 'ChildComponent title';
}
#Component({
selector: 'my-app',
template: `
<h1>Hello my Interpolated: {{title}}!</h1>
<h1 [textContent]="'Hello my Property bound: '+title+'!'"></h1>
<div #child></div>
<h1>End of parent: {{endTitle}}</h1>
`,
})
export class AppComponent implements OnInit{
public title = 'Angular 2 app';
public endTitle= 'Bye bye!';
constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {
// dynamicComponentLoader.loadIntoLocation(ChildComponent, elementRef, 'child');
}
ngOnInit():any {
this.dynamicComponentLoader.loadIntoLocation(ChildComponent, this.elementRef, 'child');
}
}
This will render the following:
Hello my Interpolated: Angular 2 app!
Hello my Property bound: Angular 2 app!
Hello my Property bound: ChildComponent title
Hello my Interpolated: ChildComponent title
End of parent: Bye bye!
I think all you have to do is set the element you want to have compiled html with the [innerHTML]="yourcomponentscopevar"
Angular provided DynamicComponentLoader class for loading html dynamically. DynamicComponentLoader have methods for inserting components. loadIntoLocation is one of them for inserting component.
paper.component.ts
import {Component,DynamicComponentLoader,ElementRef,Inject,OnInit} from 'angular2/core';
import { BulletinComponent } from './bulletin.component';
#Component({
selector: 'paper',
templateUrl: 'app/views/paper.html'
}
})
export class PaperComponent {
constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {
}
ngOnInit(){
this.dynamicComponentLoader.loadIntoLocation(BulletinComponent, this.elementRef,'child');
}
}
bulletin.component.ts
import {Component} from 'angular2/core';
#Component({
selector: 'bulletin',
templateUrl: 'app/views/bulletin.html'
}
})
export class BulletinComponent {}
paper.html
<div>
<div #child></div>
</div>
Few things you need to take care of :
Don't call loadIntoLocation inside the constructor of class . Component view is not yet created when component constructor is called. You will get error -
Error during instantiation of AppComponent!. There is no component
directive at element [object Object]
Put anchorName #child in html otherwise you will get error.
Could not find variable child
Have a look at this module https://www.npmjs.com/package/ngx-dynamic-template
After a long research, only this thing helped me. The rest of the solutions seems to be outdated.