Send data to components in VueJS + Vue Router - laravel

I can't pass data from app to compenent. After render it shows only clear html, without data from vue. All works, but without data((
My code from app.js:
var Series = Vue.component('Series', require('./components/Series.vue'),{
props: {
series: {
type: Array,
default: []
},
images: {
type: Array,
default: []
},
showPhotos: {
type: Boolean,
default: false
}
}
});
const Bar = { template: '<div>bar</div>' }
const Foo = { template: '<div>foo</div>' }
const routes = [
{ path: '/weedings', component: Series },
{ path: '/', component: Foo },
{ path: '/family', component: Foo },
{ path: '/other', component: Foo },
{ path: '/videos', component: Bar },
{ path: '/blog', component: Bar },
{ path: '/about', component: Foo },
{ path: '/contacts', component: Bar }
]
const router = new VueRouter({
routes // short for routes: routes
});
var app = new Vue({
el: "#app",
router,
data: {
series: [],
currentSerie: 0,
images: [],
showPhotos: false
},
methods: {
fetchSeries: function(){
this.$http.get('/api/fetchSeries').then((response) => {
this.series = response.body
}, (response) => {
alert("fail")
});
},
fetchPhotos: function(id){
this.showPhotos = false;
this.$http.get('/api/fetchPhotos/'+id).then((response) => {
this.images = response.body
this.showPhotos = true;
$("html, body").animate({ scrollTop: 60 }, "500");
}, (response) => {
alert("fail")
});
},
photos: function(id){
this.fetchPhotos(id)
}
},
created: function(){
this.fetchSeries()
setTimeout(function(){ require('./custom'); }, 1000);
}
});
When I dont use vue-router, all works fine. And i know i can pass data to components in this way: <my-component :artribute="value"></my-component>, but in this case IDK how to pass data.

Use function mode like this:
{
path: '/weedings',
component: Series,
props: () => (
{ series: app.series, images: app.images, showPhotos: app.showPhotos }
)
}
Check working example in JSFiddle.
Note: You have to use vuex as a centralized store for all the components in an application to be able to implement more complex scenarios.

In your routes declaration you should add props
`const routes = [
{ path: '/weedings', component: Series, props: true}]`
Here mentioned: Passing props to Vue.js components instantiated by Vue-router

Related

Pagination Apollo Client 3 - Cache merges but does not render new results when paginating

I'd love to implement nested pagination within my application. I have been reading the docs and looking at several other examples but I just can't get this to work - any help is appreciated! Thanks!
React component:
I am clicking the button to run the fetchMore function provided by the useQuery hook (apollo). The network request is going through and the new products are merged into the cache... but no new products render on the page.
export const FilterableKit = () => {
const selectedKitId = useReactiveVar(selectedKitIdVar);
const [
getKitProducts,
{ data: getKitProductsData, loading: getKitProductsLoading, fetchMore },
] = useGetKitProductsLazyQuery();
useEffect(() => {
if (selectedKitId) {
getKitProducts({
variables: {
getKitsInput: {
_id: {
string: selectedKitId,
filterBy: "OBJECTID" as StringFilterByEnum,
},
},
getProductsInput: {
config: {
pagination: {
reverse: true,
limit: 3,
},
},
},
},
});
}
}, [getKitProducts, selectedKitId]);
const kitProducts = getKitProductsData?.getKits.data?.find(
(kit) => kit?._id === selectedKitId
)?.products.data;
const handleLoadMore = () => {
if (kitProducts && kitProducts?.length > 0) {
const remaining =
getKitProductsData?.getKits.data[0]?.products.stats?.remaining;
if (remaining && remaining > 0) {
const cursor =
kitProducts[kitProducts.length - 1] &&
kitProducts[kitProducts.length - 1]?.createdAt;
fetchMore({
variables: {
getProductsInput: {
config: {
pagination: {
reverse: true,
createdAt: cursor,
},
},
},
},
});
}
}
};
return (
<CContainer>
<KitItemCards products={kitProducts} loading={getKitProductsLoading} />
<CContainer className="d-flex justify-content-center my-3">
<CButton color="primary" className="w-100" onClick={handleLoadMore}>
Load More
</CButton>
</CContainer>
</CContainer>
);
};
Type Policies: I define the "Kit" typePolicy to merge products into the correct field.
export const cache: InMemoryCache = new InMemoryCache({
typePolicies: {
Kit: {
fields: {
products: {
keyArgs: false,
merge(existing = [] as Product[], incoming: GetProductsResponse) {
if (!incoming) return existing;
if (!existing) return incoming;
const { data: products, ...rest } = incoming;
let result: any = rest;
result = [...existing, ...(products ?? [])];
return result;
},
},
},
},
});
Thanks for any pointers in the right direction! Let me know if there is something else you'd like to see.

How to emit once the observable data variable is not NULL

I'm new to RxJS, and I'm trying to figure out how to observe the data when it become available. I'm using Nuxt SSR and I'm fetching data from Firebase. The initial post value is set to null, and once the data object become available, it should run the head() function only once. I get this type error.
Cannot read property 'pipe' of null
If I initiate post: {}, as empty object, I get this type error.
post$.pipe is not a function
Appreciate if I can get some help or guidance.
// page\:post.vue
<script>
import { mapState, mapActions } from 'vuex'
import { take } from 'rxjs/operators'
export default {
fetch() {
this.fetchPost()
},
computed: {
...mapState('posts', ['post']),
},
methods: {
...mapActions('posts', ['fetchPost']),
},
head() {
const post$ = this.post
post$.pipe(take(1)).subscribe((post) => {
return {
title: this.post.title,
link: [{ rel: 'canonical', href: this.post.canonical }],
meta: [
{ hid: 'name', itemprop: 'name', content: this.post.title },
{
hid: 'description',
itemprop: 'description',
content: this.post.content,
},
],
}
})
},
}
</script>
// store\posts.js
export const state = () => ({
post: null,
})
export const mutations = {
setPost(state, payload) {
state.post = payload
},
}
export const actions = {
async fetchPost({ commit }, key) {
const doc = await postsCollection.doc(key).get()
if (doc.exists) commit('setPost', doc.dat())
},
}
Edit
Using Subject. However, there is still issue where the meta tags are generated before the post data is set.
// page\:post.vue
<script>
import { mapState, mapActions } from 'vuex'
import { take } from 'rxjs/operators'
export default {
fetch() {
this.fetchPost()
},
computed: {
...mapState('posts', ['post']),
},
methods: {
...mapActions('posts', ['fetchPost']),
},
head() {
const postSubject = new Subject()
const post = postSubject.asObservable()
postSubject.next(this.post)
post.subscribe((post) => {
return {
title: post.title,
link: [{ rel: 'canonical', href: post.canonical }],
meta: [
{ hid: 'name', itemprop: 'name', content: post.title },
{
hid: 'description',
itemprop: 'description',
content: post.content,
},
],
}
})
},
}
</script>
// store\posts.js
export const state = () => ({
post: null,
})
export const mutations = {
setPost(state, payload) {
state.post = payload
},
}
export const actions = {
async fetchPost({ commit }, key) {
const doc = await postsCollection.doc(key).get()
if (doc.exists) commit('setPost', doc.dat())
},
}
You need to subscribe to an Observable. As I understood, in your case this.post is not type of an Observable.
As this.post is populated at some point of time, you need to subscribe to an observable which should emit data when you say this.post is now populated with data. For that you can use a Subject.
See this example: link

seneca - communication between two microservices

I'm new in Seneca. I have been trying to make two microservices to communicate each other but I keep failing and get this errors:
Error: Response Error: 404 Not Found
at module.exports.internals.Utils.internals.Utils.handle_response (c:\Users\Actiview\Desktop\microservices\orderManager\node_modules\seneca-transport\lib\transport-utils.js:71:11)
at c:\Users\Actiview\Desktop\microservices\orderManager\node_modules\seneca-transport\lib\http.js:154:25
at read (c:\Users\Actiview\Desktop\microservices\orderManager\node_modules\wreck\lib\index.js:590:24)
at finish (c:\Users\Actiview\Desktop\microservices\orderManager\node_modules\wreck\lib\index.js:398:20)
at wrapped (c:\Users\Actiview\Desktop\microservices\orderManager\node_modules\hoek\lib\index.js:879:20)
at module.exports.internals.Recorder.onReaderFinish (c:\Users\Actiview\Desktop\microservices\orderManager\node_modules\wreck\lib\index.js:449:16)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at module.exports.internals.Recorder.emit (events.js:208:7)
at finishMaybe (_stream_writable.js:614:14)
=== SENECA FATAL ERROR === MESSAGE: ::: seneca: Action failed: Response Error: 404 Not Found. CODE: ::: act_execute INSTANCE :::
Seneca/pcbyi7v5c76v/1534346071465/6536/3.7.0/- DETAILS ::: {
message: 'Response Error: 404 Not Found',
pattern: '',
fn: { [Function: transport_client] id: 'host:127.0.0.2,pg:,port:8080' },
callback:
{ [Function: bound action_reply]
seneca:
Seneca {
'private$':
{ act:
{ parent:
{ start: 1534346071559,
end: 1534346071561, and more...
this is my code:
orderIndex.ts
{
const orderPlugin = require('./orderManagerPlugin');
const express = require('express');
const SenecaWeb = require('seneca-web');
const seneca = require("seneca")();
let bodyParser = require('body-parser');
var Routes = [{
prefix: '/orders',
pin: 'area:order,action:*',
map: {
fetch: { GET: true },
create: { GET: false, POST: true },
delete: { GET: false, DELETE: true },
}
}]
var config = {
routes: Routes,
adapter: require('seneca-web-adapter-express'),
context: express().use(bodyParser.urlencoded({ 'extended': 'true' })).use(bodyParser.json()),
options: {parseBody: false}
}
seneca.use(SenecaWeb,config);
seneca.use( orderPlugin );
seneca.ready(function (err) {
const app = seneca.export('web/context')();
app.listen({ host: "127.0.0.4", port: 8081 });
});
}
orderPlugin.ts
{
var plugin = function orderPlugin(options) {
var seneca = this;
var senecaEmailer;
seneca.add({ area: "order", action: "fetch" }, function (args,
done) {
var orders = this.make("orders");
orders.list$({ id: args.id }, done);
});
seneca.add({ area: "order", action: "delete" }, function (args,
done) {
var orders = this.make("orders");
orders.remove$({ id: args.id }, function (err) {
done(err, null);
});
});
seneca.add({ area: "order", action: "create" }, function (args,
done) {
console.log('create order');
senecaEmailer.act( 'role:web', {area: 'email', action:'send'} , done);
});
this.add( { init: "orderPlugin" }, function (args, done) {
senecaEmailer = require("seneca")().client({ host: "127.0.0.2", port: 8080 });
done();
});
}
module.exports = plugin;
}
emailIndex.ts
{
const mailPlugin = require('./emailingPlugin');
const express = require('express');
const SenecaWeb = require('seneca-web');
const seneca = require("seneca")();
let bodyParser = require('body-parser');
var Routes = [{
prefix: '/emails',
pin: 'area:email, action:*',
map: {
send: { GET: true },
}
}]
var config = {
routes: Routes,
adapter: require('seneca-web-adapter-express'),
context: express().use(bodyParser.urlencoded({ 'extended': 'true' })).use(bodyParser.json()),
options: {parseBody: false}
}
seneca.use(SenecaWeb,config);
seneca.use( mailPlugin );
seneca.ready(function (err) {
const app = seneca.export('web/context')();
app.listen({ host: "127.0.0.2", port: 8080 } );
});
}
emailPlugin.ts
{
import {EmailService} from './emailService';
var plugin = function emailPlugin(options) {
var seneca = this;
let mailer :EmailService ;
seneca.add({area: "email", action: "send"}, function(args, done) {
mailer.sendMail('guzon56#gmail.com', done);
});
this.add( { init: "emailPlugin" }, function (args, done) {
console.log('before init');
mailer = require('./emailService')();
console.log('after init');
done();
});
};
module.exports = plugin;
}
please help me.
Tnx.
Seneca is explained by Richard Rodger in this post. The chapter "Service Discovery" talks about meshing the microservices in a network.
For my applications I use the seneca-mesh plugin. This plugin README says:
To join the network, all a service has to do is contact one other
service already in the network. The network then shares information
about which services respond to which patterns. There is no need to
configure the location of individual services anywhere.
Reading Richard's post and the plugin documentation could be a good starting point for your project. Hope it helps!

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.

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