Parameter in $stateParams are undefined in resolve - angular-ui-router

I have a page showing a list of contact and clicking on one of the contacts in the view should switch to detail state as below:
dashboard-contacts-controller.js
vm.viewContact = function(contactId) {
console.log("Load contact " + contactId);
$state.go("app.dashboards_contact", {"id": contactId});
}
contacts-module.js
.state('app.dashboards_contact', {
url: '/dashboard-contact/:id',
views: {
'content#app': {
templateUrl: 'app/main/apps/dashboards/contacts/about/about.html',
controller: 'DashboardContactController as vm'
}
},
resolve: {
contact: ['DashboardContactsDataService', function($stateParams, DashboardContactsDataService) {
console.log($stateParams.id);
return DashboardContactsDataService.get($stateParams.id);
}
]
},
bodyClass: 'dashboard-contact'
});
$stateParams.id in resolve is always undefined.

You didnt inject $stateParams in resolve. Shouldn't it be
resolve: {
contact: ['$stateParams', DashboardContactsDataService', function($stateParams, DashboardContactsDataService) {
console.log($stateParams.id);
return DashboardContactsDataService.get($stateParams.id);
}
]
},

Related

Prisma2: How to solve n +1 Problem with Paljs

thx for any help.
Im using at the frontend the apollo-client and at the backend graphql-nexus,prisma2 and graphql-yoga server.
I want to solve the n + 1 problem with #paljs/plugins.
At the frontend I have a query posts like:
query posts{
posts {
id
favoritedBy(where: { id: { equals: $currentUserId } }) {
id
}
author {
id
avatar {
id
}
}
link {
id
}
games {
id
}
tags {
id
}
likes(where: { user: { id: { equals: $currentUserId } } }) {
id
}
}
}
Posts resolver:
import { PrismaSelect } from '#paljs/plugins'
export const posts = queryField('posts', {
type: 'Post',
list: true,
args: {
...
},
resolve: async (_parent, args, { prisma, request }, info) => {
const select = new PrismaSelect(info).value
let opArgs: FindManyPostArgs = {
take: 10,
orderBy: {
[args.orderBy]: 'desc',
},
...select
}
const post = await prisma.post.findMany(opArgs)
//The result I want to return with the "sub-models" like likes, author tags...
console.log(JSON.stringify(post, undefined, 2))
return post
},
})
I logging the queries
const prisma = new PrismaClient({
log: ['query'],
})
My Problem: With PrismaSelect, I have 5 queries more than without and If I check the request-time at the frontend I need 300-400ms longer with PrismaSelect. So what I'm doing wrong?
I saw in the #paljs/plugins doc the select in the context. Maybe that is my mistake. How can I use the select in the context?
Here ist my Context:
import { PrismaClient, PrismaClientOptions } from '#prisma/client'
import { PubSub } from 'graphql-yoga'
import { PrismaDelete, onDeleteArgs } from '#paljs/plugins'
class Prisma extends PrismaClient {
constructor(options?: PrismaClientOptions) {
super(options)
}
async onDelete(args: onDeleteArgs) {
const prismaDelete = new PrismaDelete(this)
await prismaDelete.onDelete(args)
}
}
export const prisma = new PrismaClient({
log: ['query'],
})
export const pubsub = new PubSub()
export interface Context {
prisma: PrismaClient
request: any
pubsub: PubSub
}
export function createContext(request: any): Context {
return { prisma, request, pubsub }
}
You need to know that to use my PrismaSelect plugin you need to remove the nexus-prisma-plugin package and use my Pal.js CLI to create your CRUD and ObjectType for nexus and using #paljs/nexus plugin to add in mackSchema function
import { makeSchema } from '#nexus/schema';
import * as types from './graphql';
import { paljs } from '#paljs/nexus'; // import our plugin
export const schema = makeSchema({
types,
plugins: [paljs()],// here our plugin don't use nexus-prisma-plugin
outputs: {
schema: __dirname + '/generated/schema.graphql',
typegen: __dirname + '/generated/nexus.ts',
},
typegenAutoConfig: {
sources: [
{
source: require.resolve('./context'),
alias: 'Context',
},
],
contextType: 'Context.Context',
},
});
Now add this type to your Context
export interface Context {
prisma: PrismaClient
request: any
pubsub: PubSub
select: any // here our select type
}
export function createContext(request: any): Context {
// our paljs plugin will add select object before resolver
return { prisma, request, pubsub, select: {} }
}
after you add our plugin your query will log like this
extendType({
type: 'Query',
definition(t) {
t.field('findOneUser', {
type: 'User',
nullable: true,
args: {
where: arg({
type: 'UserWhereUniqueInput',
nullable: false,
}),
},
resolve(_, { where }, { prisma, select }) {
// our plugin add select object into context for you
return prisma.user.findOne({
where,
...select,
});
},
});
},
});
Can you please try to use my pal c command to start an example from my list and try your schema and make tests with it
It is working, thx Ahmed your plugin is AWESOME!!!!!
I changed my Post-Object from
const Post = objectType({
name: 'Post',
definition(t) {
t.model.id()
t.model.authorId()
t.model.tags()
t.model.games()
t.model.link()
t.model.report()
t.model.notifications()
t.model.author()
t.model.favoritedBy({
filtering: {
id: true,
},
})
t.model.likes({
filtering: {
user: true,
},
})
}
})
to
const Post = objectType({
name: 'Post',
definition(t) {
t.string('id')
t.field('tags', {
nullable: false,
list: [true],
type: 'Tag',
resolve(parent: any) {
return parent['tags']
},
})
t.field('games', {
list: [true],
type: 'Game',
resolve(parent: any) {
return parent['games']
},
})
t.field('link', {
type: 'Link',
nullable: true,
resolve(parent: any) {
return parent['link']
},
})
t.field('notifications', {
list: [true],
type: 'Notification',
resolve(parent: any) {
return parent['notifications']
},
})
t.field('author', {
nullable: false,
type: 'User',
resolve(parent: any) {
return parent['author']
},
})
t.field('favoritedBy', {
nullable: false,
list: [true],
type: 'User',
args: {
where: 'UserWhereInput',
},
resolve(parent: any) {
return parent['favoritedBy']
},
})
t.field('likes', {
list: [true],
type: 'Like',
args: {
where: 'LikeWhereInput',
},
resolve(parent: any) {
return parent['likes']
},
})
},
})
And I also used the nexus-prisma-plugin and paljs-plugin at the same time

Nuxt dynamic route population using graphQL

In nuxtconfig.js you can use
generate: { routes() {} }
to return all the dynamic routes for your app.
All the examples use axios ie:
import axios from 'axios'
export default {
generate: {
routes: function () {
return axios.get('https://my-api/users')
.then((res) => {
return res.data.map((user) => {
return {
route: '/users/' + user.id,
payload: user
}
})
})
}
}
}
How can i do this with graphQL / apollo?
I have tried this and some other combinations...
let v
apollo: {
posts: {
query: gql`
query posts {
posts {
title
}
}
`,
result({ data, loading, networkStatus }) {
v = data
}
}
},
generate: {
subFolders: true,
routes: function() {
return {
route: '/posts/' + v.title,
payload: v
}
}
},
The error is that i dont think apollo is able to be used in nuxtconfig?
This also doesnt work
generate: {
routes: function() {
apollo: {
posts: {
query:`query posts {
posts {
title
}
}
`,
result({ data, loading, networkStatus }) {
return {
route: '/posts/' + data.title,
payload: data
}
}
}
},
}
},

How to update a store in vuex from outside?

I have an iOS app that needs to pass data to a vue front-end:
const customerStore = new Vuex.Store({
state: {
data: [
{ id:1, title: 'Foo' },
{ id:2, title: 'Bar' }
]
},
mutations: {
list (state, data) {
state.data = data
}
}
})
const ListCustomersPage = {
key: 'ListCustomersPage',
template: '#ListCustomersPage',
components: { toolbar, cellcustomer },
data() {
return {
title: 'Select Customer',
items: customerStore.state.data
}
},
methods: {
push() {
}
}
};
However, I need to mutate the store from an injection on the webview:
web.InjectJavascriptAsync("customerStore.commit('list', [])").Start()
But the list is not changed. No error is shown when calling the injection.

ui-router set params from resolve

Hi I wondering is it possible set param in ui-router data which from resolve. This example doesen't work, what's wrong ?
resolve : {
userItem : [function () {
return "name";
}]
},
params: {
title: $resolve.userItem ,
},
How about something like this
//...
resolve: {
userItem: function($stateParams){
$stateParams.title = "whatever";
return {data: "whatever"};
}
},
params:{
title:null
}
//...

How to structure my states and routing in ui-router

I´m building a e-commerce site using angular1 and ui-router (1.0.0.beta3).
But I´m not sure how to setup this up.
This is what I have in mind.
const home = {
name: 'home',
url: '/',
views: {
header: 'header',
navbar: 'navbar',
sidenav: 'sideNav',
content: 'home'
}
};
const category = {
name: 'home.category',
url: '/{url}',
views: {
content: 'categoryPage'
}
};
const product = {
name: 'home.category.product',
url: '/{url}',
views: {
content: 'productPage'
}
};
we can´t control links that come from the cms it self, "/about-us" and "/category-x" can be a category or a cms-page so we added a route state where we can resolve the entity_type (product, category or cms-page)
.state('home.router', {
url: '/{url}?:{page:int}&:{limit:int}&:id',
params: {
limit: null,
category: null,
page: {
dynamic: true
},
id: {
dynamic: true
}
},
templateProvider: ['urlRewrite', function(urlRewrite) {
switch (urlRewrite.entity_type) {
case 'category':
return '<category-page limit="$stateParams.limit" page="$stateParams.page" category="{name: $resolve.urlRewrite.request_path, id: $resolve.urlRewrite.entity_id}"/>';
case 'product':
return '<product-page id="$resolve.urlRewrite.entity_id"/>';
case 'cms-page':
default:
return '<page url="$resolve.urlRewrite.target_path" />';
}
}],
resolve: {
urlRewrite: ['UrlRewrite', '$stateParams', function(UrlRewrite, $stateParams) {
return UrlRewrite.getUrlRewrite($stateParams.url);
}]
}
});
the problem is that category and route url patterns collide.
and we can´t really use parent/child inherits etc etc..
How should we go about resolving "unknown" urls?
Plunkr: http://plnkr.co/edit/gXzDO5j3arP8QCrpwL9k?p=preview
Let me provide you with the sample snippet. It will give you the idea.
appName.config(['$stateProvider','$urlRouterProvider', '$httpProvider' ,function ($stateProvider, $urlRouterProvider, $httpProvider) {
// $urlRouterProvider.otherwise('/login');
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
var $localStorage = $injector.get('$localStorage');
if($localStorage.user){
return '/dashboard'
}else {
return '/login'
}
});
$stateProvider
.state('login', {
url: '/login',
views: {
'': {
templateProvider: function ($templateFactory, $localStorage) {
return $templateFactory.fromUrl(asset_path('angular/templates/base/login.html'));
},
controller: 'LoginCtrl'
}
}
})
$httpProvider.interceptors.push('Interceptor');
}]);

Resources