Stencil.js: How to use utils function in index.html - javascript

i'm creating a popup stenciljs component.
File structure:
popup-element
src
utils
popup-manager
components
popup-element
popup-element.tsx
index.html
...
Now i try to insert component to DOM from function:
popup-manager.ts
export function createMiniNotification(notificationContent: string, mountTarget: HTMLElement = document.body): HTMLElement {
const notify = document.createElement('popup-element');
notify.setAttribute('content', notificationContent);
mountTarget.appendChild(notify);
}
How can I use this function in index.html (in development mode)?

Update:
You can add exports to src/index.ts and then those will be available at /build/index.esm.js.
// src/index.ts
export const createMiniNotification = (msg: string) => console.log(msg);
<script type="module">
import { createMiniNotification } from '/build/index.esm.js';
createMiniNotification('Hi');
</script>
Original Answer:
I'd suggest you create a wrapping component, e. g. app-root and call your function from there, e. g. in its componentDidLoad lifecycle hook:
import { Component, Host, h } from '#stencil/core';
import { createMiniNotification } from '../utils/popup-manager';
#Component({ tag: 'app-root' })
export class AppRoot {
componentDidLoad() {
createMiniNotification(/* ... */);
}
render() {
return <Host />;
}
}
Then you can just add this wrapper component in your index.html:
<app-root></app-root>

Related

Vue JS - custom properties on vue component gives TS errors

I have created some Vue middleware and I am trying to add a custom property to one of my components in Vue like so:
middleware.js:
import { VueConstructor } from 'vue/types';
function eventPlugin(vue: VueConstructor): void {
const Socket = new someClass();
Object.defineProperties(vue.prototype, {
$socket: {
get: function get() {
return Socket;
},
},
});
vue.$socket = Socket;
}
myComponent.js
const MyComponent = Vue.extend({
name: 'MyComponent',
$socket: {
event(data: any) {
}
},
methods: {
MyMethod() {
}
}
})
app.js
import Vue from 'vue';
import eventPlugin from './middleware.js';
import MyComponent from './myComponent.js'
Vue.use(eventPlugin);
export default new Vue({
render: (h) => h(MyComponent),
}).$mount('#app');
The custom property I am trying to add here is obviously socket. The problem is when I add it I get typescript errors:
Object literal may only specify known properties, and 'socket' does
not exist in type 'ComponentOptions<Vue, DefaultData,
DefaultMethods, DefaultComputed, PropsDefinition<Record<string,
any>>, Record<...>>'.
As you can see in middleware.js I have tried defining the property there so I am not sure why I am receiving the error?
When adding instance properties or component options, you also need to augment the existing type declarations.
Based on Augmenting Types for Use with Plugins (Vue 2):
To type-hint the $socket instance property:
declare module 'vue/types/vue' {
interface VueConstructor {
$socket: string
}
}
export {}
To type-hint the $socket component option:
import Vue from 'vue'
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
$socket?: string
}
}
export {}
The type declarations above should go in a .d.ts file in your src directory. If using VS Code, any new .d.ts files might require restarting VS Code to load.

How do I create a function library which I can used across all my Vuejs components?

I currently writing a financial application using Vue.js and Vuetify. I have a few component files and javascript files like
Dashboard.vue
Cashflow.vue
NetWorth.vue
stores.js <- Vue Vuex
I have some functions which I need to use across all the Vue.js and javascript files. Would it be possible for me to perhaps write a function library which can be used across all
the component and js files.
function moneyFormat(num)
function IRRCalc(Cashflow)
function TimeValueMoneyCalc(I,N,PV,FV,PMT)
function PerpetualAnnuityCalc(I,PV)
function CarLoanInstallment(V,N)
function HouseLoanInstallment(V,N)
I know in C it is very simple just #include<financial.h> was wondering is there something similar in javascript.
Thanks.
There are 3 ways to do this:
1/You can create a helper.js file and import it to .vue files
// helper.js
export default {
function moneyFormat(num) { // some logic}
}
// Dashboard.vue
<script>
import helper from "helper.js" //the path may change depends on where you put the js file
methods: {
useHelper(value) {
helper.moneyFormat(value)
}
}
</script>
2/Another way is bind the function to Vue prototype
in main.js
Vue.prototype.$moneyFormat= function moneyFormat(num) {}
then in Dashboard.vue just call this.$moneyFormat(num). No need to import anything
3/ Use mixins. You can search online on how to use this https://v2.vuejs.org/v2/guide/mixins.html
You can create a single JS file that holds all the helper/util methods, and then export them individually:
export function moneyFormat(num) { ... }
export function IRRCalc(Cashflow) { ... }
export function TimeValueMoneyCalc(I,N,PV,FV,PMT) { ... }
export function PerpetualAnnuityCalc(I,PV) { ... }
export function CarLoanInstallment(V,N) { ... }
export function HouseLoanInstallment(V,N) { ... }
Then, you can simply import individual methods as of when needed, i.e.:
import { CarLoanInstallment, HouseLoanInstallment } from '/path/to/helper/file';
This can be quite usefuly for tree-shaking when you're bundling with webpack, for example, so that you don't bundle unnecessary functions that are never used in your project.
You can use Mixin
In your main.js, add Vue.mixin:
import Vue from "vue";
import App from "./App.vue";
Vue.mixin({
methods: {
helloWorld() {
alert("Hello world");
}
}
});
new Vue({
render: h => h(App)
}).$mount("#app");
and then you can call helloWorld() method from your component script with this.helloWorld() or just helloWorld() from the template.
You also can use filters if the method is to apply common text formatting
In your main.js, add Vue.filter:
import Vue from "vue";
import App from "./App.vue";
Vue.filter("capitalize", function(value) {
if (!value) return "";
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
});
new Vue({
render: h => h(App)
}).$mount("#app");
and then you can do {{ "some text" | capitalize }} to apply capitalize filter on "some text"
Example here: https://codesandbox.io/s/heuristic-dirac-esb45?file=/src/main.js:0-226

Error in Vue i18n with TypeScript: "Property '$t' does not exist on type 'VueConstructor'. " . How can I fix it?

In project some common function are in separate .ts files.
How can I use i18 in that cases:
// for i18n
import Vue from 'vue'
declare module 'vue/types/vue' {
interface VueConstructor {
$t: any
}
}
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
t?: any
}
}
(()=>{
const test = Vue.$t('auth.title');
console.log( test )
})()
Return an error:
Property '$t' does not exist on type 'VueConstructor<Vue>"
How can I fix it?
we can achieve the same like below
Step 1: create a separate index.ts file inside a i18n folder (you can do it your own way - root level or any where in your app)
i18n/index.ts
import Vue from 'vue';
import VueI18n from 'vue-i18n';
// register i18n module
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: 'nb-NO', //if you need get the browser language use following "window.navigator.language"
fallbackLocale: 'en',
messages: {en, no},
silentTranslationWarn: true
})
const translate = (key: string) => {
if (!key) {
return '';
}
return i18n.t(key);
};
export { i18n, translate}; //export above method
Step 2: make sure to use(import) above in main.ts
main.ts
import { i18n } from '#/i18n';
new Vue({ i18n, render: h => h(app) }).$mount('#app')
after above configuration we should be able to use translation in any place that we want in our application
Step 3: How to use it in .ts and .vue files
// first import it into the file
import { translate, i18n } from '#/i18n';
//this is how we can use translation inside a html if we need
<template>
<h1>{{'sample text' | translate}}</h1>
</template>
//this is how we can use translation inside a .ts or .vue files
<script lang='ts'>
//normal scenario
testFunc(){
let test = `${translate('sample text')}`;
console.log(test );
}
//in your case it should be like below
(()=>{
const test = `${translate('auth.title')}`;
console.log( test )
})()
</script>
I hope that this will help you to resolve your issue.

How do I import JSX into .tsx file (not in React)?

I am not using React.
I am using Stenciljs.
I have the following .tsx file:
export class MyComponent {
#Prop() message: string;
render() {
return (<div>{this.message}</div>);
}
}
I want to do this instead:
import myTemplate from '../my-template.??';
export class MyComponent {
#Prop() message: string;
render() {
return (myTemplate);
}
}
with ../my-template.?? containing:
<div>{this.message}</div>
Is it possible and how ? Thanks in advance for any help :)
Yes, you can absolutely do this, there are just a couple of things you need to tidy up:
Main file
import { Template } from '../template'; // No need for file extension but we're using a named export so we need the curly braces around 'Template'
export class MyComponent {
#Prop() message: string;
render() {
return ( // You don't technically need the parentheses here as you're just returning one thing
<Template /> // When outputting an imported component, it goes in angle brackets and the backslash closes it like an HTML element
)
}
}
Template
import React from 'react'; // template needs React
export const Template = () => { // defining the export in this way is known as a named export
return (
<p>A message here</p>
)
}
Okay, so that's going to get you a message output which is from your template. However, you were asking about passing a message to that template for it to output. That's totally easy as well - you just need to get some props in there. Here is the modified version of the above:
Main file
import { Template } from '../template';
export class MyComponent {
#Prop() message: string;
render() {
return (
<Template messageToOutput={message} /> // The first argument is the name of the prop, the second is the variable you defined above
)
}
}
Template
import React from 'react';
export const Template = (props) => { // props are received here
return (
<p>{props.messageToOutput}</p> // props are used here
)
}
That's how you pass data around in React - hope that helps!

how to use a function from another js file in reactjs?

i have a file something.js which has a function:
someFunction: function(arg1, arg2){
//code blocks
}
In my app.js file i want to call this function in the app class. I have imported the something.js file like this import { someFunction } from './something.js';. Now i am trying to use it in a function in the app class
var res = someFunction("abc", 2);
console.log(res);`
i am getting a error Uncaught TypeError: (0 , _something.someFunction) is not a function
Some help would be appreciated.
You need to write it like this:
something.js file -
module.exports = {
A: funtion(){
},
B: funtion(){
}
}
Then import it like this:
import {A} from 'something';
Or use it like this:
something.js file -
export A(){
}
export B(){
}
Then import it like this:
import {A} from 'something';
Read this article: https://danmartensen.svbtle.com/build-better-apps-with-es6-modules
In order to import something, you need to export it from the other module.
For example, you could export class YourComponent extends React.Component in something.js.
Then in the other file you can import { YourComponent } from './something'
You could, for example, in something.js do something like
const MyClass = {
methodName() { return true; }
}
export { MyClass as default } // no semi-colon
Then in the other file you could
import WhateverIWant from 'something';
WhateverIWant.methodName(); // will return true
Edit:
An in-depth explanation with lots of examples is available here.
You could either do: in your something.js file: module.exports = function(){}..
and in your app.js file:
const functionName = require('./path_to_your_file');
Or export somethingFunction = {} and in app.js:
import { somethingFunction } from './path_to_your_file'
Or last: export default somethingFunction = {} and in app.js:
import whateverNameYouChoose from './path_to_your_file'
Let me know if that did the trick! :)
In your something.js file, you can add export someFunction near the bottom of the file. This will then allow you to import that function using the import { someFunction } from './something.js'; you have earlier.

Categories