how to declare method in 'vuejs' as for 'Handlebars.registerHelper'? - methods

I'm going from "Handlebarjs" to "Vuejs".
I want to declare a method that is invoked in several parts of my code.
As for Handlebars.registerHelper ();
please help.

You can prototype your components before initializing your app
import axios from 'axios'
Vue.prototype.$http = axios
new Vue(...)
axios will be available in every component you declare
...
methods: {
getSomething: function() {
this.$http.get('blablabla', ...
...
You can register your functions as well

Related

Use next-intl outside of a react component

Is there any way to use next-intl outside of a react component?
For now I get t by calling the hook useTranslations, and then pass its instance to my function:
function formatFoo(t, foo) {
if ....
t('bar');
}
export default function MyComponent() {
const t = useTranslations();
return <div>{formatFoo(t, "bar")}</div>
}
I wish I could just import t from next-intl as i18next permits for example.

How to build a Model Layer in Vue3 just like other MVC language?

my name is DP, I have 2 years Vue2 experience, but I am new to Vue3. I am learning Vue3 recently, as I found the "setup(Composition API)" just like the "Controller(in MVC)" that I did in other language, so I am trying to build my test Vue3 project in MVC way, but I go some problem can anyone help? thx!
MVC Plan
M - use class
V - use <template> ... </template>
C - use setup
My Problem
working: using loadTopic_inSetup().then() in setup is working, because topicList_inSetup is defined in setup() too.
not working: using loadTopic_inModel() in setup is not working, I guess some kind data keep problem, because in console I can see the data already got from API
as u can see, I am not expert for js/ts, I am a backend developer, so if you know how to do it, plz help thx very much.
BTW, VUE is greet, I love it.
My Code
//APIBased.ts
import { ajax } from "#/lib/eeAxios"
export class APIBased {
//load data with given url and params
loadData(apiPath: string, params?: object): Promise<any> {
apiPath = '/v1/'+apiPath
return ajax.get(apiPath, params)
}
}
//Topic.ts
import { APIBased } from "./APIBased";
import { ref } from 'vue'
export class Topic extends APIBased {
//try keep data in model
topicList: any = ref([]);
constructor() {
super()
}
//direct return ajax.get, let setup do the then+catch
loadTopic_inSetup() {
return super.loadData('topics', { t_type_id: 1 })
}
//run ajax get set return data to this.topicList, keep data in model
loadTopic_inModel() {
super.loadData('topics', { t_type_id: 1 }).then((re) => {
console.log(re.data)
this.topicList = re.data
})
}
}
//EETest.vue
<template>
<EELayoutMainLayout>
<template v-slot:mainContent>
<h1>{{ "Hello Vue3 !!" }}</h1>
<hr/>
{{to.topicList}} //not working... just empty array
<hr/>
{{topicList_inSetup}} //working... topic list return from API show here.
</template>
</EELayoutMainLayout>
</template>
<script lang="ts">
import { defineComponent, getCurrentInstance, ref } from 'vue'
import EELayoutMainLayout from '#/components/eeLayout/EELayoutMainLayout.vue'
import { Topic } from "#/models/Topic";
export default defineComponent({
name: 'EETest',
props: {
},
setup() {
let topicList_inSetup = ref([])
const to = new Topic()
//try keep data in setup, it's working
to.loadTopic_inSetup().then((re) => {
topicList_inSetup.value = re.data
console.log(re.data)
})
//try keep data in model, the function is run, api return get, but data not show, even add ref in model
to.loadTopic_inModel()
return {
topicList,
to,
}
},
components: {
EELayoutMainLayout,
},
})
</script>
A few digressions before solving the problem. Maybe you are a java developer. I personally think it is inappropriate to write the front end with Java ideas. The design of vue3's setup is more inclined to combined functional programming
To fully understand why you need some pre knowledge, Proxy and the get and set method of Object
They correspond to the two core apis in vue, reactive and ref,
The former can only be applied to objects( because proxy can only proxy objects),The latter can be applied to any type(primary for basic javascript types, get and set can apply for any type)
You can modify the code to meet your expectations
loadTopic_inModel() {
super.loadData('topics', { t_type_id: 1 }).then((re) => {
console.log(re.data)
this.topicList.value = re.data
})
}
You cannot modify a ref object directly, a test case to explain what is reactive
when ref function is called, a will be like be wrapped in a class has value properties, and has get and set method
the effect function will call the arrow function, and in this time, the get method of a will be called and it will track as a dependence of the effect function, when a changed, the set method of a will be called, and it will trigger the arrow function,
so when you direct modify the a, the setter method will never trigger, the view will not update
const a = ref(1)
let dummy
let calls = 0
effect(() => {
calls++
dummy = a.value
})
expect(calls).toBe(1)
expect(dummy).toBe(1)
a.value = 2
expect(calls).toBe(2)
expect(dummy).toBe(2)
// same value should not trigger
a.value = 2
expect(calls).toBe(2)

Apollo Client Error, Objects are not valid as a React child (found: [object Promise])

I'm getting a weird error when attempting to do async/await on my graphql query. Not sure what to do here.
import React, { Component } from "react";
import { ApolloConsumer } from 'react-apollo';
import Landing from '../modules/landing/index.js';
import getUser from '../shared/services/get-user';
export default class extends Component {
checkLoggedIn = async (client) => {
const response = await getUser(client);
console.log(response);
}
render() {
return (
<ApolloConsumer>
{client => (
<div>
{this.checkLoggedIn(client)}
<Landing />
</div>
)}
</ApolloConsumer>
)
}
}
If I remove the async await syntax, the app proceeds to execute my getUser query. However, when I try to do this with async/await. My app shows the error above. Is there something about ApolloConsumer that I do not understand?
The reason you are getting the error is because async function returns a promise. And, you are trying to render a promise inside of the render method. This isn't Apollo specific error, React simply doesn't allow this.
The reason why it works when you don't have the async there is because the function returns undefined which react treats as null in the render method and doesn't render anything.

Ember 2.5 observe session property changes

I've monkey-patched my router to store the current route components in a session variable:
var Router = Ember.Router.extend({
customSession: Ember.inject.service('session-custom'),
location: config.locationType,
didTransition: function() {
this._super(...arguments);
this.get('customSession').set('currentEntity', this.get('currentRouteName').split('.')[0]);
this.get('customSession').set('currentDetailView', this.get('currentRouteName').split('.')[1]);
}
});
I know that this is not the cleanest of solutions, but writing the session to the console proves that at least those parameters are set.
In my controller, I'd like to listen for changes in these parameters, but somehow this does not work:
import Ember from 'ember';
import ApplicationController from './application';
export default ApplicationController.extend({
customSession: Ember.inject.service('session-custom'),
currentRouteNameChanged: Ember.observer('customSession.currentEntity', function () {
console.log("route changed");
})
});
i.e. "route changed" is never printed to the console.
This seems quite an easy fix, but I haven't been able to find a solution on SO.
Thanks!
Perhaps consider using an initializer to inject your session-custom service into your application’s controllers. To get there, some suggestions…
First, in the Router, and elsewhere, use the conventional, camelized short-hand to inject your service, like this:
sessionCustom: Ember.inject.service(),
...and be sure to reference sessionCustom in your code, instead of customSession.
Next, create a session-custom initializer, and inject the service into your application’s controllers:
export function initialize(application) {
application.inject('controller', 'sessionCustom', 'service:session-custom');
}
export default {
name: 'session-custom',
initialize,
};
Observing route changes from the controller should now be successful:
export default Ember.Controller.extend({
currentRouteNameChanged: Ember.observer(
'sessionCustom.currentEntity', function() {
console.log("CONTROLLER: ", this.get('sessionCustom.currentEntity'));
}
),
});
These changes, of course, can also be observed from the service itself:
export default Ember.Service.extend({
currentEntity: '', // <-- it's helpful to explicitly declare
currentRouteNameChanged: Ember.observer(
'currentEntity', function() {
console.log("SERVICE: ", this.get('currentEntity'));
}
),
});
I’ve created an Ember Twiddle to demonstrate this solution.

Do I need to bind to a component to use the apollo react client even if it has no UI?

I'm doing some business logic around an implementation of the Auth0 lock widget and need to call some graphql mutations to sign in. In this case there is no UI to render since it's simply a call to Auth0's lock.show() method. However, looking at all the apollo client examples with react - the graphql method seems to bind the functions to a component.
Can I call a gql mutation directly without binding it to a react component?
What's the best way to get the client from the ApolloProvider if I'm not in a component? Is there a static singleton instance i can reference from ApolloProvider or do I need to pass the client reference from the root application compoment?
You can use the withApollo() decorator exported from apollo-client to access the client as a prop inside a component. The ApolloProvider exposes the client to its child components through context. The withApollo() higher-order component accesses the client on context and passes it to its child as a prop.
So, if the auth.lock() function is being triggered by some type of UI interaction or one of the React lifecycle methods, you can access the client in that component and either call the mutation directly in the component or pass it as an argument through to the function that calls auth.lock().
However, since you want to access the client outside of the React tree, you have to access the client in a different way.
Alternatively, you can export the same client that you pass as a prop to ApolloProvider and import it wherever you need to use it in the app. Note, this singleton pattern won't work with server-side rendering. Example:
root.jsx
import React from 'react';
import { Router, browserHistory } from 'react-router';
import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { syncHistoryWithStore } from 'react-router-redux';
import routes from './routes';
const networkInterface = createNetworkInterface({
uri: '/graphql',
opts: {
credentials: 'same-origin'
}
});
export const client = new ApolloClient({
networkInterface
});
export const store = configureStore(browserHistory, client);
export const history = syncHistoryWithStore(browserHistory, store);
export default function Root() {
<ApolloProvider client={client} store={store}>
<Router
history={history}
routes={routes}
/>
</ApolloProvider>
}
some-other-module.js
import { client } from 'app/root';
export default function login(username, password) {
return client.mutate({
// ...mutationStuff
});
}
You can import ApolloProvider like this:
import { ApolloProvider } from "#apollo/client";

Resources