How do I register component globally in Quasar? - quasar-framework

I have a component which I'll be using in every page of my web-app. To simplify my work how do I register this component globally? I used nuxt once and it was so easy by npm #nuxtjs/global-components. What is process with Quasar? Thank you!

You can create a boot file with all your global components, e.g. global-components.js
There you need to import your components and apply them to Vue:
import Vue from 'vue'
import MyComponent from '../component/MyComponent.vue'
Vue.component('my-component', MyComponent)
Lastly you need to call your boot file in quasar.conf.js
boot: ["global-components"]
More info

In Quasar 2:
import { boot } from 'quasar/wrappers'
import MyComponent from '../components/MyComponent.vue'
export default boot(async ({ app }) => {
app.component('my-component', MyComponent)
})

I use this solution and it helps us to dynamically register component
Create a file in src/boot folder for example i created register-my-component.js and white this code:
// src/boot/register-my-component.js
import upperFirst from "lodash/upperFirst";
import camelCase from "lodash/camelCase";
export default ({ app }) => {
const requireComponent = require.context(
"src/components",
true,
/[A-Z-_]\w+\.(vue)$/
);
requireComponent.keys().forEach((fileName) => {
const componentConfig = requireComponent(fileName);
const componentName = upperFirst(
camelCase(
fileName
.split("/")
.pop()
.replace(/\.\w+$/, "")
)
);
app.component(componentName, componentConfig.default || componentConfig);
});
};
Now register this boot file in quasar.conf.js. you can find it in the root directory
// app boot file (/src/boot)
// --> boot files are part of "main.js"
// https://quasar.dev/quasar-cli/boot-files
boot: [ ..., "register-my-component" ],
Now you don't need to import and register components anymore (NOTE: as you can see only components in src/component register automatically. So if you write your component in other paths you need to import and register that)

Related

Nuxt 3 environment variables for static site [duplicate]

I have .env file in the project root, and in my nuxt config I am using variables to configure ReCaptcha like this:
import dotenv from 'dotenv'
dotenv.config()
export default {
modules: [
['#nuxtjs/recaptcha', {
siteKey: process.env.RECAPTCHA_SITE_KEY,
version: 3,
size: 'compact'
}],
]
}
and in .env like this:
RECAPTCHA_SITE_KEY=6L....
but the application always failed with console log error:
ReCaptcha error: No key provided
When I hard-code ReCaptcha key directly like that: siteKey: 6L.... app start working, so I guess the problem is with reading .env props in nuxt.config
do you have any idea how to fix it?
EDIT:
I tried update my nuxt.config by #kissu recommendation and by example which I found here: https://www.npmjs.com/package/#nuxtjs/recaptcha
so there is new nuxt.config which also not working:
export default {
modules: [
'#nuxtjs/recaptcha',
],
publicRuntimeConfig: {
recaptcha: {
siteKey: process.env.RECAPTCHA_SITE_KEY,
version: 3,
size: 'compact'
}
}
}
If your Nuxt version is 2.13 or above, you don't need to use #nuxtjs/dotenv or anything alike because it is already backed into the framework.
To use some variables, you need to have an .env file at the root of your project. This one should be ignored by git. You can then input some keys there like
PUBLIC_VARIABLE="https://my-cool-website.com"
PRIVATE_TOKEN="1234qwer"
In your nuxt.config.js, you have to input those into 2 objects, depending of your use case, either publicRuntimeConfig or privateRuntimeConfig:
export default {
publicRuntimeConfig: {
myPublicVariable: process.env.PUBLIC_VARIABLE,
},
privateRuntimeConfig: {
myPrivateToken: process.env.PRIVATE_TOKEN
}
}
Differences: publicRuntimeConfig can basically be used anywhere, while privateRuntimeConfig can only be used during SSR (a key can only stay private if not shipped to the browser).
A popular use case for the privateRuntimeConfig is to use it for nuxtServerInit or during the build process (either yarn build or yarn generate) to populate the app with headless CMS' API calls.
More info can be found on this blog post: https://nuxtjs.org/blog/moving-from-nuxtjs-dotenv-to-runtime-config/
Then, you will be able to access it into any .vue file directly with
this.$config.myPublicVariable
You access it into Nuxt's /plugins too, with this syntax
export default ({ $axios, $config: { myPublicVariable } }) => {
$axios.defaults.baseURL = myPublicVariable
}
If you need this variable for a Nuxt module or in any key in your nuxt.config.js file, write it directly with
process.env.PRIVATE_TOKEN
Sometimes, the syntax may differ a bit, in this case refer to your Nuxt module documentation.
// for #nuxtjs/gtm
publicRuntimeConfig: {
gtm: {
id: process.env.GOOGLE_TAG_MANAGER_ID
}
},
PS: if you do use target: server (default value), you can yarn build and yarn start to deploy your app to production. Then, change any environment variables that you'd like and yarn start again. There will be no need for a rebuild. Hence the name RuntimeConfig!
Nuxt3 update
As mentioned here and in the docs, you can use the following for Nuxt3
nuxt.config.js
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
runtimeConfig: {
public: {
secret: process.env.SECRET,
}
}
}
In any component
<script setup lang="ts">
const config = useRuntimeConfig()
config.secret
</script>
In a composable like /composables/test.js as shown in this comment
export default () => {
const config = useRuntimeConfig()
console.log(config.secret)
}
Here is the official doc for that part.
You can also use the env property with Nuxt
nuxt.config.js:
export default {
// Environment variables
env: {
myVariable: process.env.NUXT_ENV_MY_VAR
},
...
}
Then in your plugin:
const myVar = process.env.myVariable
It's very easy. Providing you an example with axios/nuxt
Define your variable in the .env file:
baseUrl=http://localhost:1337
Add the variable in the nuxt.config.js in an env-object (and use it in the axios config):
export default {env: {baseUrl: process.env.baseUrl},axios: {baseURL: process.env.baseUrl},}
Use the env variable in any file like so:
console.log(process.env.baseUrl)
Note that console.log(process.env) will output {} but console.log(process.env.baseUrl) will still output your value!
For nuxt3 rc11, in nuxt.conf.ts file:
export default defineNuxtConfig({
runtimeConfig: {
public: {
locale: {
defaultLocale: process.env.NUXT_I18N_LOCALE,
fallbackLocale: process.env.NUXT_I18N_FALLBACK_LOCALE,
}
}
},
...
and in .env file:
NUXT_I18N_LOCALE=tr
NUXT_I18N_FALLBACK_LOCALE=en
public: is very important otherwise it cannot read it and gives undefined error.
For v3 there is a precise description in the official docs
You define a runtimeConfig entry in your nuxt.config.[ts,js] which works as initial / default value:
export default defineNuxtConfig({
runtimeConfig: {
recaptchaSiteKey: 'default value' // This key is "private" and will only be available within server-side
}
}
You can also use env vars to init the runtimeConfig but its written static after build.
But you can override the value at runtime by using the following env var:
NUXT_RECAPTCHA_SITE_KEY=SOMETHING DYNAMIC
If you need to use the config on client-side, you need to use the public property.
export default defineNuxtConfig({
runtimeConfig: {
public: {
recaptchaSiteKey: 'default value' // will be also exposed to the client-side
}
}
}
Notice the PUBLIC part in the env var:
NUXT_PUBLIC_RECAPTCHA_SITE_KEY=SOMETHING DYNAMIC
This is very strange because we can't access process.env in Nuxt 3
In the Nuxt 3, we are invited to use the runtime config, but this is not always convenient, because the Nuxt application context is required.
But in a situation where we have some plain library, and we don’t want to wrap it in plugins nor composables functions, declaring global variables through vite / webpack is best:
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
define: {
MY_API_URL: JSON.stringify(process.env.MY_API_URL)
}
}
})
And then you can use in any file without dancing with a tambourine:
// some-file.ts
console.log('global var:', MY_API_URL) // replaced by vite/webpack in real value

Twilio adding custom attributes from studio into flex agent info bar

I am using a "send to flex node" in my twilio studio application.
In this node I am passing:
{"verified": "{{flow.variables.verified}}", "accountid": "{{flow.variables.accountid}}"}
I have created a sample plugin but how can I modify it so that the existing agent info tab also displays those two parameters ? Maybe under CUSTOMER CONTEXT or in its own container?
I understand that they will need to be used as follows in the code :
${task.attributes.verified} and ${task.attributes.accountid}
Many thanks
You want to create a component that uses the task context so that it has access to the task object as one of its props. You can then add that component to the task info panel.
For example, here's an account component that displays the attributes you want:
import React from "react";
import { withTaskContext } from "#twilio/flex-ui";
function AccountComponent({ task }) {
return <div>
<p>${task.attributes.verified} and ${task.attributes.accountid}</p>
</div>;
}
export default withTaskContext(AccountComponent);
Then, in your main plugin file, within the init function, add the component to the task info panel. Using sortOrder: -1 will place it at the top of the component.
import React from "react";
import { FlexPlugin } from "flex-plugin";
import AccountComponent from "./components/AccountComponent";
const PLUGIN_NAME = "FlexTaskInfoPlugin";
export default class FlexTaskInfoPlugin extends FlexPlugin {
constructor() {
super(PLUGIN_NAME);
}
init(flex, manager) {
flex.TaskInfoPanel.Content.add(
<AccountComponent key="account-component"></CustomerName>,
{ sortOrder: -1 }
);
}
}

Creating a folder outside the exe in Electron

How would I create a folder outside the Electron exe.
I'm planning to build the app as a portable windows exe so I'm not sure how to get the path of the exe.
EDIT #1:
I have tried to use app.getPath("exe"); on the main process, but I'm getting a reference error whenever I run the app ReferenceError: exe is not defined
It was indeed app.getPath("exe"), but it has to be implemented using the Electron event emitter pattern.
To have access to the data I triggered the path on the main process.
ipcMain.on("CALL_PRINT_EXE_FILE_PATH", (event) => {
console.log("printing the file path of the exe");
const exePath = app.getPath("exe");
console.log(`exePath: ${exePath}`);
mainWindow.send("PRINT_EXE_FILE_PATH", exePath);
});
Then inside the renderer (I use React), I emit the event and also trigger an event listener.
const { ipcRenderer } = window.require("electron");
...
componentDidMount() {
ipcRenderer.send("CALL_PRINT_EXE_FILE_PATH");
}
componentWillMount() {
ipcRenderer.on("PRINT_EXE_FILE_PATH", this.handlePrintExePath);
}
componentWillUnmount() {
ipcRenderer.removeListener("PRINT_EXE_FILE_PATH", this.handlePrintExePath);
}
...
handlePrintExePath(event, exePath) {
console.log("printing the app exe in the render");
console.log(`exeFilePath: ${exePath}`);
}

Make Changes To sw-precache service-worker

I am using sw-precache and I understand that in order to edit the service-worker.js file I need to do this (as detailed in the service-worker.js file)
// This file should be overwritten as part of your build process.
// If you need to extend the behavior of the generated service worker, the best approach is to write
// additional code and include it using the importScripts option:
// https://github.com/GoogleChrome/sw-precache#importscripts-arraystring
but I do not know where to add the importscripts() code. Does it go in the service-worker.js file? Surely that gets over-ridden on each project build.
Just include it like so:
importScripts: ['custom-offline-import.js']
Here is an example with an config including the importScripts config option at the end:
var packageJson = require('../package.json');
var swPrecache = require('../lib/sw-precache.js');
var path = require('path');
function writeServiceWorkerFile(rootDir, handleFetch, callback) {
var config = {
cacheId: packageJson.name,
runtimeCaching: [{
// See https://github.com/GoogleChrome/sw-toolbox#methods
urlPattern: /runtime-caching/,
handler: 'cacheFirst'
}],
staticFileGlobs: [rootDir + '/**/*.{js,html,css,png,jpg,gif}'],
stripPrefix: rootDir,
importScripts: ['custom-offline-import.js']
};
swPrecache.write(path.join(rootDir, 'service-worker.js'), config, callback);
}
Hope I could help you!
Add it to the sw-precache-config.js file.
Good example here:
Rewrite URL offline when using a service worker

Open external file with Electron

I have a running Electron app and is working great so far. For context, I need to run/open a external file which is a Go-lang binary that will do some background tasks.
Basically it will act as a backend and exposing an API that the Electron app will consume.
So far this is what i get into:
I tried to open the file with the "node way" using child_process but i have fail opening the a sample txt file probably due to path issues.
The Electron API expose a open-file event but it lacks of documentation/example and i don't know if it could be useful.
That's it.
How i open an external file in Electron ?
There are a couple api's you may want to study up on and see which helps you.
fs
The fs module allows you to open files for reading and writing directly.
var fs = require('fs');
fs.readFile(p, 'utf8', function (err, data) {
if (err) return console.log(err);
// data is the contents of the text file we just read
});
path
The path module allows you to build and parse paths in a platform agnostic way.
var path = require('path');
var p = path.join(__dirname, '..', 'game.config');
shell
The shell api is an electron only api that you can use to shell execute a file at a given path, which will use the OS default application to open the file.
const {shell} = require('electron');
// Open a local file in the default app
shell.openItem('c:\\example.txt');
// Open a URL in the default way
shell.openExternal('https://github.com');
child_process
Assuming that your golang binary is an executable then you would use child_process.spawn to call it and communicate with it. This is a node api.
var path = require('path');
var spawn = require('child_process').spawn;
var child = spawn(path.join(__dirname, '..', 'mygoap.exe'), ['game.config', '--debug']);
// attach events, etc.
addon
If your golang binary isn't an executable then you will need to make a native addon wrapper.
Maybe you are looking for this ?
dialog.showOpenDialog refer to: https://www.electronjs.org/docs/api/dialog
If using electron#13.1.0, you can do like this:
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
dialog.showOpenDialog(function(file_paths){
console.info(file_paths) // => this gives the absolute path of selected files.
})
when the above code is triggered, you can see an "open file dialog" like this (diffrent view style for win/mac/linux)
Electron allows the use of nodejs packages.
In other words, import node packages as if you were in node, e.g.:
var fs = require('fs');
To run the golang binary, you can make use of the child_process module. The documentation is thorough.
Edit: You have to solve the path differences. The open-file event is a client-side event, triggered by the window. Not what you want here.
I was also totally struggling with this issue, and almost seven years later the documentation is quite not clear what's the case with Linux.
So, on Linux it falls under Windows treatment in this regard, which means you have to look into process.argv global in the main processor, the first value in the array is the path that fired the app. The second argument, if one exist, is holding the path that requested the app to be opened. For example, here is the output for my test case:
Array(2)
0: "/opt/Blueprint/b-test"
1: "/home/husayngonzalez/2022-01-20.md"
length: 2
So, when you're creating a new window, you check for the length of process.argv and then if it was more than 1, i.e. = 2 it means you have a path that requested to be opened with your app.
Assuming you got your application packaged with the ability to process those files, and also you set the operating system to request your application to open those.
I know this doesn't exactly meet your specification, but it does cleanly separate your golang binary and Electron application.
The way I have done it is to expose the golang binary as a web service. Like this
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
//TODO: put your call here instead of the Fprintf
fmt.Fprintf(w, "HI there from Go Web Svc. %s", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/api/someMethod", handler)
http.ListenAndServe(":8080", nil)
}
Then from Electron just make ajax calls to the web service with a javascript function. Like this (you could use jQuery, but I find this pure js works fine)
function get(url, responseType) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = responseType;
request.onload = function() {
if (request.status == 200) {
resolve(request.response);
} else {
reject(Error(request.statusText));
}
};
request.onerror = function() {
reject(Error("Network Error"));
};
request.send();
});
With that method you could do something like
get('localhost/api/somemethod', 'text')
.then(function(x){
console.log(x);
}

Resources