Global configuration of ngx-bootstrap datepicker format - ngx-bootstrap

Is it possible to globally configure a date format for the ngx-bootstrap datepicker?
The documentation mentions the BsDatepickerConfig class and how to pass it to each individual datepicker, but im a bit surprised that there seems to be no possibility to configure this globally (at least not documented)
https://valor-software.com/ngx-bootstrap/#/datepicker#bs-datepicker-config

This is not yet documented, but it can be achieved pretty easy. We have several demos of that for different components (tooltips, popovers, etc) and the code for datepicker will be almost the same. If you want to configure datepickers globally, replace basic BsDatepickerConfig with your one in providers section of your component or module.
export function getDatepickerConfig(): BsDatepickerConfig {
return Object.assign(new BsDatepickerConfig(), {
dateInputFormat: 'YYYY-MM-DD'
});
}
#NgModule({
...
providers: [{ provide: BsDatepickerConfig, useFactory: getDatepickerConfig }]
})
Example - https://stackblitz.com/edit/angular-tvahsw?file=app%2Fapp.module.ts

Related

Is it possible to use DayJs in ant design Vue (antdv) in DatePickers instead of MomentJs?

I tryed to replace momentjs in project on antdv, and find this advice:
"We also provide another implementation, which we provide with
antd-dayjs-webpack-plugin, replacing momentjs with Day.js directly
without changing a line of existing code. More info can be found at
antd-dayjs-webpack-plugin."
https://2x.antdv.com/docs/vue/faq
So then i tryed to do same steps like in instruction https://github.com/ant-design/antd-dayjs-webpack-plugin. But i just changed webpack-config.js on vue-config.js and in code:
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin');
module.exports = {
plugins: [
new AntdDayjsWebpackPlugin()
]
}
// on
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin');
module.exports = {
configureWebpack: (config) => {
config.plugins.push(
new AntdDayjsWebpackPlugin(),
);
}
}
But then i got mistake 502 Bad Gateway.
If i deleted configureWebpack mistake was still there. And then i deleted require and mistake was gone.
Also i found what in page with this plugin there was word about React but not about Vue.
So i had few questions:
Is it possible to use DayJs in antdv DatePickers? With plugins or any ways.
Is it mistake in FAQ? How i can tall about this issue (if it is)? I didnt found any method to communicate with them.

Integrating Mollie payments in NestJS backend

I am trying to integrate Mollie payments into my NestJS backend.
To make a connection with Mollie, I have to use their MollieClient function. However, when I try to use it in a service I get the error:
Nest can't resolve dependencies of the NewUserService (UserService, MailService, ConfigService, JwtService, ?). Please make sure that the argument Object at index [4] is available in the NewUserModule context.
I am pretty sure this means I have to add a Mollie module/service to the NewUserModule, but I think the package doesn't actually come with a module made for NestJS. So if I try to make a Mollie module/service or use the MollieClient in another service, it asks me to provide it whilst I don't have anything to provide.
I'm pretty new to NestJS and backend development in general, so am I mistaken? Or is there a module added in the installed package?
If there isn't a module, should I make one? What exactly should be in such a module? Is there some sort of guide for it?
I realise this might be a rather vague series of questions, but I'm not very sure how to approach this.
Edit:
Rewrote the question for clarification.
Thanks in advance!
The message means, that Nest does not now how to resolve the 5th constructor argument of your NewUserService. I assume this is something like a MollieService?
You need to add MollieService as Provider to your NewUserModule:
#Module({
imports: [...],
controllers: [...],
providers: [
...otherProviders,
MollieService
]
})
export class NewUserModule {}
Or you can create a separate MollieModule and import it in NewUserModule:
#Module({
providers: [ MollieService ],
exports: [ MollieService ] // export MollieService, so that other modules can use it
})
export class MollieModule {}
#Module({
imports: [MollieModule],
controllers: [...],
providers: [...] // no need to provide MollieService here, because it's imported from MollieModule
})
export class NewUserModule {}
Of course you must also implement the MollieService using their SDK.
A recommend to read the Documentation on Modules. They are a little hard to understand at a first sight, but a powerful concept!
EDIT:
I would suggest to wrap the MollySDK in a service. This way you're not dealing with molly at various places in your app and prevent leaking it's api and types into your services.
#Injectable()
export class MollyService {
private readonly mollyClient: WhateverType;
constructor() {
this.mollyClient = createMollieClient({ apiKey: 'test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM' });
}
createPayment() {
this.mollieClient.payments.create({...});
}
}
This service could be injected as usual.
However if you really want to use the molly-client directly, you have to use a custom provider
#Module({
providers: [{
provides: 'MOLLY_CLIENT',
useFactory: () => createMollieClient({ apiKey: 'test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM' }) // you could also use useValue instead of useFactory
}],
exports: [ 'MOLLY_CLIENT' ]
})
export class MollieModule {}
Then inject it into NewUsersService like so:
constructor(#Inject('MOLLY_CLIENT')private readonly mollyClient: WhateverType) {}

Extend several new paths to a single page in Nuxt

I am struggeling with the nuxt folder/route structure for a project:
I want to achieve:
All of them should show pages/data/index.vue:
www.example.com/data
www.example.com/data/region
www.example.com/data/region/industry
And then access the parameter region or industry via the $route-class.
If I add _region folder and an _industy.vue it will show those files and I want to show and use the index.vue.
EDIT: Since region and industry are probably dynamic.
You could use this setup in your nuxt.config.js file
export default {
router: {
extendRoutes(routes, resolve) {
routes.push(
{
name: 'data-region-industry',
path: '/data/*/*',
component: resolve(__dirname, 'pages/data/index.vue'),
},
{
name: 'data-region',
path: '/data/*',
component: resolve(__dirname, 'pages/data/index.vue'),
},
)
}
}
}
With this configuration, you can go to either /data, /data/:region or /data/:region/:industry with only your index.vue file. No need to make some strange directories or file, you can keep all in one single place.
PS: the order is important. Put the most specific at top, otherwise /data/* will also catch /data/*/* and you'll never reach data-region-industry. This can be double-checked pretty quickly in the router tab of the Vue devtools.
This was taken from the official documentation: https://nuxtjs.org/docs/2.x/features/file-system-routing#extendroutes
I highly recommend giving it a read, especially if you are using Named views.
As for the URL catch, never heard of $route-class but you could make some kind of split on /, pretty doable!
you could use query in the url instead of params.
www.example.com/data
www.example.com/data/?region=x
www.example.com/data/?region=x&?industry=y
you are still able to access the query data via $route.query. if you don't want to use query you have to manually overwrite vue router of nuxt as far as I know.

“window is not defined” in Nuxt.js

I get an error porting from Vue.js to Nuxt.js.
I am trying to use vue-session in node_modules. It compiles successfully, but in the browser I see the error:
ReferenceError window is not defined
node_modules\vue-session\index.js:
VueSession.install = function(Vue, options) {
if (options && 'persist' in options && options.persist) STORAGE = window.localStorage;
else STORAGE = window.sessionStorage;
Vue.prototype.$session = {
flash: {
parent: function() {
return Vue.prototype.$session;
},
so, I followed this documentation:
rewardadd.vue:
import VueSession from 'vue-session';
Vue.use(VueSession);
if (process.client) {
require('vue-session');
}
nuxt.config.js:
build: {
vendor: ['vue-session'],
But I still cannot solve this problem.
UPDATED AUGUST 2021
The Window is not defined error results from nodejs server side scripts not recognising the window object which is native to browsers only.
As of nuxt v2.4 you don't need to add the process.client or process.browser object.
Typically your nuxt plugin directory is structured as below:
~/plugins/myplugin.js
import Vue from 'vue';
// your imported custom plugin or in this scenario the 'vue-session' plugin
import VueSession from 'vue-session';
Vue.use(VueSession);
And then in your nuxt.config.js you can now add plugins to your project using the two methods below:
METHOD 1:
Add the mode property with the value 'client' to your plugin
plugins: [
{ src: '~/plugins/myplugin.js', mode: 'client' }
]
METHOD 2: (Simpler in my opinion)
Rename your plugin with the extension .client.js and then add it to your plugins in the nuxt.config.js plugins. Nuxt 2.4.x will recognize the plugin extension as to be rendered on the server side .server.js or the client side .client.js depending on the extension used.
NOTE: Adding the file without either the .client.js or .server.js extensions will render the plugin on both the client side and the server side. Read more here.
plugins: ['~/plugins/myplugin.client.js']
There is no window object on the server side rendering side. But the quick fix is to check process.browser.
created(){
if (process.browser){
console.log(window.innerWidth, window.innerHeight);
}
}
This is a little bit sloppy but it works. Here's a good writeup about how to use plugins to do it better.
Its all covered in nuxt docs and in faq. First you need to make it a plugin. Second you need to make your plugin client side only
plugins: [
{ src: '~/plugins/vue-notifications', mode: 'client' }
]
Also vendor is not used in nuxt 2.x and your process.client not needed if its in plugin with ssr false
In Nuxt 3 you use process.client like so:
if (process.client) {
alert(window);
}
If you've tried most of the answers here and it isn't working for you, check this out, I also had the same problem when using Paystack, a payment package. I will use the OP's instances
Create a plugin with .client.js as extension so that it can be rendered on client side only. So in plugins folder,
create a file 'vue-session.client.js' which is the plugin and put in the code below
import Vue from 'vue'
import VueSession from 'vue-session'
//depending on what you need it for
Vue.use(VueSession)
// I needed mine as a component so I did something like this
Vue.component('vue-session', VueSession)
so in nuxt.config.js, Register the plugin depending on your plugin path
plugins:[
...
{ src: '~/plugins/vue-session.client.js'},
...
]
In index.vue or whatever page you want to use the package... import the package on mounted so it is available when the client page mounts...
export default {
...
mounted() {
if (process.client) {
const VueSession = () => import('vue-session')
}
}
...
}
You can check if you're running with client side or with the browser. window is not defined from the SSR
const isClientSide: boolean = typeof window !== 'undefined'
Lazy loading worked for me. Lazy loading a component in Vue is as easy as importing the component using dynamic import wrapped in a function. We can lazy load the StepProgress component as follows:
export default {
components: {
StepProgress: () => import('vue-step-progress')
}
};
On top of all the answers here, you can also face some other packages that are not compatible with SSR out of the box and that will require some hacks to work properly. Here is my answer in details.
The TLDR is that you'll sometimes need to:
use process.client
use the <client-only> tag
use a dynamic import if needed later on, like const Ace = await import('ace-builds/src-noconflict/ace')
load a component conditionally components: { [process.client && 'VueEditor']: () => import('vue2-editor') }
For me it was the case of using apex-charts in Nuxt, so I had to add ssr: false to nuxt.config.js.

Implementing Emojis in a VueJs App

I am looking to setup emojis to my chat-app project.
I really liked the emojis in slack / tweeter and I would like to have something similar.
I found the following libraries: (if anyone can suggest a better library I would love to hear)
emojionearea
wdt-emoji-bundle
I am not sure how to load these libraries and use them in a VueJS app.
Could anyone please assist with how to load and use them?
I would like to mention I tried to use emoji-mart-vue
but not sure how to add the the component to the template at run time.
Thanks a lot
tldr; Checkout demo and code on JSFiddle
This answer is divided into two parts. First part deals with how to import all the stuff into the environment while the second part deals with how to use it Vue.
This solution uses EmojiOne as the emoji provider and EmojioneArea to provide emoji autocomplete behavior.
Part 1: Adding the libraries
There are three ways in which you can do this.
Using Global <script> tag (not recommended for anything serious): You can add the <script> tags for all the dependencies in order and simply start using the Global objects.
Add these <script> in order:
https://code.jquery.com/jquery-3.3.1.min.js
https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.min.js
https://cdn.jsdelivr.net/npm/emojione#3.1.6/lib/js/emojione.min.js
https://cdnjs.cloudflare.com/ajax/libs/jquery.textcomplete/1.8.4/jquery.textcomplete.min.js
https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea.min.js
Using AMD modules (using require.js): You can use the following configuration to load these modules asynchronously using require.js
require.config({
paths: {
'jquery': 'https://code.jquery.com/jquery-3.3.1',
'Vue': 'https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue',
'emojione': 'https://cdn.jsdelivr.net/npm/emojione#3.1.6/lib/js/emojione',
'jquery.textcomplete': 'https://cdnjs.cloudflare.com/ajax/libs/jquery.textcomplete/1.8.4/jquery.textcomplete',
'emojionearea': 'https://cdnjs.cloudflare.com/ajax/libs/emojionearea/3.4.1/emojionearea'
},
shim: {
'emojione': {
'exports': 'emojione'
}
}
})
You can then require these modules in your entry point as
require(['jquery', 'Vue', 'emojione'], function($, Vue, emojione){ /* ... */ })
Using webpack: All the above libraries are available via npm and you install and use them just as you would do with any other library. No special config required.
BONUS: Using webpack with require.js and offloading network and caching loads to CDN!
I often use this setup for my projects and this improves reliability and performance of your site. You can use webpack.externals to instruct webpack to not bundle any vendor dependencies and instead you provide them yourself, either by manually adding <script> tags or using require.js.
Start by adding this to your webpack.<whatever>.js
//...
output: {
libraryTarget: 'umd' // export app as a library
},
//...
externals: {
'jquery': 'jquery',
'vue': 'Vue',
'emojione': 'emojione'
},
//...
Then, in your require.js entry, add this
//...
map: {
// any module requesting jquery should get shield
"*": {
"jquery": "jquery-shield"
},
// shield should get original jquery
"jquery-shield": {
"jquery": "jquery"
},
// patch plugins
"jquery.textcomplete": {
"jquery": "jquery"
},
"emojionearea": {
"jquery": "jquery"
}
}
//...
// define shield, require all the plugins here
define('jquery-shield', ['jquery', 'jquery-textcomplete', 'emojionearea'], function($){ return $ })
and then add require(...) your webpack bundle
Part 2: Using EmojiOne with Vue
As the OP mentioned his/her case is to use emojis in a chat app, I would also explain the solution with that case, though this can (and should) be modified for other use cases too!
The solution focuses on two aspects. First is to simply display the emoji in a message component, i.e., no need to display an emoji picker dialog and second is to display a emoji picker dialog whilst the user is typing into (say) a textarea.
To achieve the first goal, you can use a message component like,
Vue.component('message', {
props: ['content'],
render: function(h){
return h('div', {
class: { 'message': true }
}, [
h('div', {
class: { 'bubble': true },
domProps: {
innerHTML: emojione.toImage(this.content)
}
})
])
}
})
This would create a <message /> component which you can use as
<message content="Hey :hugging:!!" />
which will render
<div class="message">
<div class="bubble">
Hey <img class="emojione" alt="🤗" title=":hugging:" src="...">!!
</div>
</div>
Now, to create a <message-box /> component that will display an emoji picker to assist in autocomplete, do as follows
Vue.component('message-box', {
template: `<div class="message-box"><textarea></textarea></div>`,
mounted(){
// find the input
$(this.$el).find('textarea').emojioneArea()
}
})
And that's it! Although it may seem like a lot, the crux of the solution is quiet simple! Just use emojione.toImage(str) to get a DOM string and apply it to the Vue component (you can also use v-html to do this but IMO render() is a bit more sleek!). And for the displaying the picker, you just call $(...).emojioneArea() on the <textarea /> once the component is mounted.
Make sure to checkout full code example at https://jsfiddle.net/riyaz_ali/5Lhex13n