Nuxt.js : combine transition(to, from) and enter / leave events - vue.js

So I have this code, it decides what to do on a transition between two pages and it works well :
export default {
transition: {
mode: 'out-in',
css: false,
beforeEnter (el) {
console.log('set transition');
},
enter (el, done) {
console.log('enter transition');
done();
},
leave (el, done) {
console.log('leave transition');
done();
},
}
}
Now I would like to specify what to do depending on what the next page is. So I've to use the transition(to, from) method according to the documentation. But unfortunately I can't mix this function with parameters like mode: 'out-in' and I can't manage to call the leave(el, done) function with the to, from parameters.
Does anyone knows how to combine this ? Thanks.

Maybe you found the solution, but I managed to combine transition with routes (to, from) and the object transition.
Let me explain :
If you look a the TypeScript declaration for vue, especially the ComponentOptions interface (node_modules/#nuxt/types/app/vue.d.ts)
Here's what we have :
declare module 'vue/types/options' {
// eslint-disable-next-line no-unused-vars,#typescript-eslint/no-unused-vars
interface ComponentOptions<V extends Vue> {
// eslint-disable-next-line #typescript-eslint/ban-types
asyncData?(ctx: Context): Promise<object | void> | object | void
fetch?(ctx: Context): Promise<void> | void
fetchKey?: string | ((getKey: (id: string) => number) => string)
fetchDelay?: number
fetchOnServer?: boolean | (() => boolean)
head?: MetaInfo | (() => MetaInfo)
key?: string | ((to: Route) => string)
layout?: string | ((ctx: Context) => string)
loading?: boolean
middleware?: Middleware | Middleware[]
scrollToTop?: boolean
transition?: string | Transition | ((to: Route, from: Route | undefined) => string | Transition)
validate?(ctx: Context): Promise<boolean> | boolean
watchQuery?: boolean | string[] | ((newQuery: Route['query'], oldQuery: Route['query']) => boolean)
meta?: { [key: string]: any }
}
}
The transition attribute is defined as follow :
transition?: string | Transition | ((to: Route, from: Route | undefined) => string | Transition)
So, by using the function approach, you must give either a string or a Transition object.
Example :
transition(to, from) {
if(!from) {
// returns a string
return 'my-custom-css-animation';
}
// returns an object Transition
return {
name: 'custom',
appear:false,
css: false,
beforeLeave() {
// before leave hook
},
leave(el, done) {
// leave hook
},
beforeEnter(el) {
// before enter hook
},
enter(el, done) {
// Enter hook
}
}
}

You should use pageTransition instead.
And did you try with a function?
export default {
pageTransition (to, from) {
if (!from) { return 'slide-left' }
return +to.query.page < +from.query.page ? 'slide-right' : 'slide-left'
}
}
Doc here: https://fr.nuxtjs.org/api/pages-transition/#fonction

Related

Nuxt Store - CanĀ“t get all values in commit

In Vuex i try to send some values to a store, like this.
getStorage(
{ commit },
name: String | undefined = undefined,
objectA: ObjectA | undefined = undefined,
objectB: ObjectB | undefined = undefined
) {
if (selectedItinerary) {
commit('setA', objectA, objectB)
} else if (name) {
commit('setB', name)
}
},
The problem: Only get name value, objectA and objectB return undefinied.
So: Somebody say what's wrong? Maybe can only send one param?
UPDATE 1
Calling dispatch
this.$store.dispatch('business/getLocalStorage', {
name: this.name,
})
Store
getLocalStorage({ commit }, item) {
if (item.name) {
commit('setLocalStorageItinerary', item.name)
}
}
setLocalStorageItinerary(state, { name }: { name: string }) {
if (name) {
const itinerary = new LocalStorage()
itinerary.name = name
state.itinerary = itinerary
}
},
Assuming getStorage is an action, which receive the Vuex context as the first argument and a payload as the second, just wrap your values up inside an object before passing it as the payload.
eg.
somewhere in your app...
let payload = {
name: someValue,
objectA: someObject,
objectB: someOtherObject
}
this.$store.dispatch('getStorage', payload)
actions.js
getStorage({ commit }, payload) {
if (selectedItinerary) {
commit('setA', payload.objectA, payload.objectB)
} else if (payload.name) {
commit('setB', payload.name)
}
}
It isn't clear from your example where selectedItinerary is defined, but I think you get the gist from the above.

Delete item from pinia state

I am new to vue and I have just started using pinia. I wanna delete an item from array but it does not work
here is my store
import {defineStore} from 'pinia'
export interface ObjectDto {
input: string,
}
interface ObjectDtoInterface {
objects: Array<ObjectDto>
}
export const useSearchHistoryStore = defineStore('objectsStore', {
state: (): ObjectDtoInterface => {
return {
objects: [] as ObjectDto[]
}
},
actions: {
add(dto: ObjectDto) {
if (this.objects
.filter(shd => dto.input === shd.input)
.length === 0) {
this.objects.unshift(dto)
}
},
delete(obj: ObjectDto) {
this.objects = this.objects.filter(e => !(e.input === obj.input))
}
}
})
and here is the function from different .ts file
function delete(obj: ObjectDto) {
objectsStore.delete(obj)
}
add action works perfect, it adds item to the state but when I try to delete an item, nothing happens. The data I pass to delete method is 100% good because I checked this many times
Filter does not mutate the original object, you need to reasing
delete(obj: ObjectDto) {
this.objects = this.objects.filter(e => !(e.input === obj.input))
}
more info https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Nest JS authorization with CASL doesn't work as expected

EXPECTING:
Be able to get user info with id equal to my id only (which is saved in JWT token).
CURRENT RESULT:
I am able to get info about all users with some id.
Used Nest Js docs while creating this solution.
Do appreciate your help.
/casl-ability.factory.ts
type Subjects = InferSubjects<typeof User | typeof Role | 'User'> | 'all';
export type AppAbility = Ability<[Action, Subjects]>;
export class CaslAbilityFactory {
createForUser(userDataFromJWT: JwtAccessTokenInput) {
const { can, cannot, build } = new AbilityBuilder<
Ability<[Action, Subjects]>
>(Ability as AbilityClass<AppAbility>);
// TESTING THIS CASE
can(Action.Read, User, {
id: userDataFromJWT.sub,
});
return build({
detectSubjectType: (item) =>
item.constructor as ExtractSubjectType<Subjects>,
});
}
private hasRole(roles: unknown[], role: UserRoles): boolean {
return roles.includes(role);
}
}
/getUser.policyHandler.ts
export class GetUserPolicyHandler implements IPolicyHandler {
handle(ability: AppAbility) {
return ability.can(Action.Read, User);
}
}
/types.ts
export enum Action {
Manage = 'manage',
Create = 'create',
Read = 'read',
Update = 'update',
Delete = 'delete',
}
export interface IPolicyHandler {
handle(ability: AppAbility): boolean;
}
type PolicyHandlerCallback = (ability: AppAbility) => boolean;
export type PolicyHandler = IPolicyHandler | PolicyHandlerCallback;
/policies.guard.ts
#Injectable()
export class PoliciesGuard implements CanActivate {
constructor(
private reflector: Reflector,
private caslAbilityFactory: CaslAbilityFactory,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const policyHandlers =
this.reflector.get<PolicyHandler[]>(
CHECK_POLICIES_KEY,
context.getHandler(),
) || [];
const ctx = GqlExecutionContext.create(context);
const { user }: { user: JwtAccessTokenInput } = ctx.getContext().req;
const ability = this.caslAbilityFactory.createForUser(user);
return policyHandlers.every((handler) =>
this.execPolicyHandler(handler, ability),
);
}
private execPolicyHandler(handler: PolicyHandler, ability: AppAbility) {
if (typeof handler === 'function') {
return handler(ability);
}
return handler.handle(ability);
}
}
user.resolver.ts
#Resolver(() => User)
export class UserResolver {
constructor(private readonly userService: UserService) {}
#Query(() => User, { name: 'user' })
#UseGuards(PoliciesGuard)
#CheckPolicies(new GetUserPolicyHandler())
#UseInterceptors(UserNotExistsByIDInterceptor)
async findOne(#Args('id', { type: () => Int }) id: number): Promise<User> {
return await this.userService.findOne(id);
}
}
possible duplicate of NestJS + CASL + Mongoose: CASL cannot infer subject type from Mongoose Schema
if you're using mongoose you need to inject the model to allow InferSubjects to retrieve the type thus allowing you to use filters and fields.

vue-test-utils how to use trigger's options

I want to test el-button if it can change to the correct view by $router,but I am confused weather the trigger supportted cause i find this in its document
The trigger method takes an optional options object. The properties in
the options object are added to the Event.
Note that target cannot be added in the options object.
const wrapper = mount(MyButton)
wrapper.trigger('click', {
button: 0
})
but failed and i get this info
TypeError: Cannot set property type of [object Event] which has only a
getter
65 | // expect(mockFn).toBeCalled
66 | // expect(mockFn).toBeCalledTimes(1)
67 | wrapper.find(ElementUI.Button).trigger('click', {
| ^
68 | id: 1,
69 | type: 'view'
70 | })
vue file
<el-button
plain
type="primary"
#click="changeView(-1, 'edit')">
newPicture
</el-button>
js
changeView(id, type) {
if (type === 'view') {
this.$router.push({ path: './detail', query: { id, type }})
} else if (type === 'edit') {
this.$router.push({ path: './edit', query: { id, type }})
}
},
And I want to write a test file for this button
...
it('add button click', () => {
const mockFn = jest.fn()
wrapper.setMethods({
changeView: mockFn
})
wrapper.find(ElementUI.Button).trigger('click', {
id: 1,
type: 'view'
})
wrapper.update()
expect(mockFn).toBeCalled
console.log(wrapper.vm.$route.path)
})
...
How can I fix this?
the options your passing are js $event properties. here's a list of them: https://www.w3schools.com/jsref/obj_event.asp
when you trigger that click event, the changeView will be called, with the parameters you passed to it(-1 and 'edit'). they are not event properties and you dont pass them as options. so your test whould look like:
it('add button click', () => {
const mockFn = jest.fn()
wrapper.setMethods({
changeView: mockFn
})
wrapper.find(ElementUI.Button).trigger('click');
wrapper.update();
expect(mockFn).toBeCalledWith(-1,'edit');
})

Vue.js | Filters is not return

I have a problem.
I am posting a category id with http post. status is returning a data that is true. I want to return with the value count variable from the back. But count does not go back. Return in function does not work. the value in the function does not return from the outside.
category-index -> View
<td>{{category.id | count}}</td>
Controller File
/**
* #Access(admin=true)
* #Route(methods="POST")
* #Request({"id": "integer"}, csrf=true)
*/
public function countAction($id){
return ['status' => 'yes'];
}
Vue File
filters: {
count: function(data){
var count = '';
this.$http.post('/admin/api/dpnblog/category/count' , {id:data} , function(success){
count = success.status;
}).catch(function(error){
console.log('error')
})
return count;
}
}
But not working :(
Thank you guys.
Note: Since you're using <td> it implies that you have a whole table of these; you might want to consider getting them all at once to reduce the amount of back-end calls.
Filters are meant for simple in-place string modifications like formatting etc.
Consider using a method to fetch this instead.
template
<td>{{ categoryCount }}</td>
script
data() {
return {
categoryCount: ''
}
},
created() {
this.categoryCount = this.fetchCategoryCount()
},
methods: {
async fetchCategoryCount() {
try {
const response = await this.$http.post('/admin/api/dpnblog/category/count', {id: this.category.id})
return response.status;
} catch(error) {
console.error('error')
}
}
}
view
<td>{{count}}</td>
vue
data() {
return {
count: '',
}
},
mounted() {
// or in any other Controller, and set your id this function
this.countFunc()
},
methods: {
countFunc: function(data) {
this.$http
.post('/admin/api/dpnblog/category/count', { id: data }, function(
success,
) {
// update view
this.count = success.status
})
.catch(function(error) {
console.log('error')
})
},
},