React-router: Passing data to component via route - json

I generate the routing of my app with the help of a data object which contains information about the routes, the desired path (slug), the according component and eventually sub-routes (nestedRoutes). If a route has nested routes I would like to pass them to the component as a data object and use them in the component e.g. for a sidebar navigation.
The routing is working fine, but I don’t get the data nestedRoutes={route.nestedRoutes} passed to the component.
If you like please take a look at my code snippet:
var data = {
"routes": [
{
"title": "MLS Styleguide",
"slug": "/mls-styleguide",
"component": MLSStyleguide,
"nestedRoutes": [
{
"title": "Basic Typography",
"slug": "/mls-styleguide",
"component": Typography,
"isIndexRoute": true
},
{
"title": "Form & Fields",
"slug": "/mls-styleguide/forms-fields",
"component": FormsFields
},
{
"title": "Form Sections",
"slug": "/mls-styleguide/form-sections",
"component": FormSections
},
{
"title": "Filters",
"slug": "/mls-styleguide/filters",
"component": Filters
},
{
"title": "Side Panels & Containers",
"slug": "/mls-styleguide/side-panels-containers",
"component": SidePanelsContainers
},
{
"title": "Tiles & Content",
"slug": "/mls-styleguide/tiles-content",
"component": TilesContent
},
{
"title": "Tooltips & Notifications",
"slug": "/mls-styleguide/tooltips-notifications",
"component": TooltipsNotifications
}
]
},
{
"title": "Playground",
"slug": "/playground",
"component": Playground
}
]
}
module.exports = (
<Route path="/" component={App}>
<IndexRoute component={Home}/>
{data.routes.map(
function(route) {
if (route.nestedRoutes) {
return (
<Route path={route.slug} nestedRoutes={route.nestedRoutes} key={route.title} component={route.component}>
{route.nestedRoutes.map(
function(nestedRoute) {
if (nestedRoute.isIndexRoute) {
return (
<IndexRoute key={nestedRoute.title} component={nestedRoute.component}/>
)
} else {
// {console.log(nestedRoute.slug)}
return (
<Route path={nestedRoute.slug} key={route.title} component={nestedRoute.component}/>
)
}
}
)}
</Route>
)
} else {
// console.log(route.slug)
return <Route path={route.slug} foo="bar" key={route.title} component={route.component}/>
}
}
)}
</Route>
)
Any comment or hint in the right direction is welcome, thanks!
EDIT
Code of the receiving component.
Please don’t wonder! The links data in the getInitialState() function serves as a workaround at the moment. When the component actually receives the this.props.nestedRoutes this will be removed.
I hope you get the idea!
export default React.createClass({
getInitialState(){
return {
links: [
{
"title": "Basic Typography",
"slug": "/mls-styleguide/"
},
{
"title": "Form & Fields",
"slug": "/mls-styleguide/forms-fields"
},
{
"title": "Form Sections",
"slug": "/mls-styleguide/form-sections"
},
{
"title": "Filters",
"slug": "/mls-styleguide/filters"
},
{
"title": "Side Panels & Containers",
"slug": "/mls-styleguide/side-panels-containers"
},
{
"title": "Tiles & Content",
"slug": "/mls-styleguide/tiles-content"
},
{
"title": "Tooltips & Notifications",
"slug": "/mls-styleguide/tooltips-notifications"
},
]
}
},
render() {
return (
<div>
<Sidebar className="left">
<SideNavbar links={this.state.links}/>
{/*<SideNavbar links={this.props.nestedRoutes}/>*/}
</Sidebar>
<div className="content-container">
{console.log(this.props.nestedRoutes)}
<h2>MLS Styleguide</h2>
{this.props.children}
</div>
</div>
)
}
})

It seems that I am not able to understand the provided solutions.
But I found a workaround: I just took the data, put it in a separate file and imported it in both files. It serves the purpose, it is simple and it is done.
Thank you all for your support!

Related

Vue.js Filtered list Method

I am still learning Vue.js. At the moment I am trying to make a simple filtered list method that pulls the data from a json file in Vue. I think that I am having trouble figuring out the correct syntax.
I just cant seem to get it right. Any help is more than welcome :)
This is Vue file:
<template>
<section>
<ul>
<li v-for="product in rings" :key="product">
{{product.title}}
</li>
</ul>
</section>
</template>
<script>
import data from '#/assets/data.json';
export default {
data() {
return {
products: []
}
},
methods: {
computed: {
rings(){
return this.products.filter(product => product.type == 'Ring')
}
}
}
}
</script>
And this is the Json file:
{ "products": [
{
"title": "Ring 1",
"description": "something",
"type": "Ring",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
},
{
"title": "Halskæde 1",
"description": "something",
"type": "Halskæde",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
},
{
"title": "Armbånd 1",
"description": "something",
"type": "Armbånd",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
},
{
"title": "Ørering 1",
"description": "something",
"type": "Ørering",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
}
]
}
You imported the data but never used anywhere inside the component:
import data from '#/assets/data.json';
// notice the data here is just a variable and it has nothing to do with the
// component's data property
export default {
data () {
return {
products: data.products // init products with imported data
}
},
Or with the destructuring syntax:
import { products } from '#/assets/data.json';
export default {
data () {
return {
products // init products with imported data
}
},

Set next step for the waterfall dialogue in Microsoft BotBuilder NodeJS SDK

I am using Microsoft Bot Framework for my facebook messenger bot. I want to load the dialog data from json files instead of hard coding in the js file. I would like to configure the next step in the dialog, based on result from the "current" step, which is part of the json file configuration, something like this.
{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "goto step 2"
},
{
"result": "option2",
"action": "goto step 5"
}
]
}
]
}
I would like to process all the incoming messages and respond with correct dialog or correct step in the dialog for the user.
I am trying something like this;
handleMessage = function (session) {
var step = session.dialogData["BotBuilder.Data.WaterfallStep"] || 0;
// check response data from previou step and identify the next step.
// set the waterfall step id
session.dialogData["BotBuilder.Data.WaterfallStep"] = 2;
session.send("Hello");
}
var bot = new builder.UniversalBot(connector, function (session) {
handleMessage(session);
})
.set('storage',tableStorage);
With this code, I am always getting step as zero for session.dialogData["BotBuilder.Data.WaterfallStep"] even after setting this to a different number.
Also, as soon as I set the waterfall step number, all other state data that is stored in my table storage for this conversation is gone.
Storage data before setting waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 0
}
},
{
"id": "*:welcome",
"state": {
"BotBuilder.Data.WaterfallStep": 1
}
},
{
"id": "BotBuilder:prompt-text",
"state": {
"options": {
"prompt": {
"type": "message",
"agent": "botbuilder",
"source": "facebook",
"address": {
"id": "mid.$cAAAlr-0LRH9niO21L1hV6hs83GuJ",
"channelId": "facebook",
"user": {
"id": "XXXX",
"name": "XXXX"
},
"conversation": {
"isGroup": false,
"id": "XX"
},
"bot": {
"id": "XXX",
"name": "XXX"
},
"serviceUrl": "https://facebook.botframework.com"
},
"text": "what do you want to next"
//ignored for simplicity
},
"promptAfterAction": true,
"libraryNamespace": "*"
},
"turns": 0,
"lastTurn": 1517594116372,
"isReprompt": false
}
}
],
"lastAccess": 1517594112740,
"version": 0
}
}
After I set the waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 2
}
}
],
"lastAccess": 1517602122416,
"version": 0
}
}
Interestingly the step number is saved to the database (but in session state) but my "session" variable do not have this value anywhere. Also, even after configuring custom state service, the serviceUrl is still https://facebook.botframework.com which I thought is the default state service used if there is no state service set for the bot.
Per your code, as your bot actually contains only one waterfall step: handleMessage(session);, which raised your issue. You can consider to create multiple dialogs from json configration instead of complex waterfall steps.
Here is my quick test, for your information:
const json = `
[{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "dialog2"
},
{
"result": "option2",
"action": "dialog3"
}
]
}
]
},{
"name":"dialog2",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig2."
}]
}
]
},{
"name":"dialog3",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig3."
}]
}
]
}]
`;
const generateSignleStep = (step) => {
return (session, args, next) => {
step.forEach(sentence => {
switch (sentence.type) {
case 'quickReplies':
let choices = sentence.options.map(item => {
return item.value
});
let card = new builder.ThumbnailCard(session)
.text(sentence.value)
.buttons(sentence.options.map(choice => new builder.CardAction.imBack(session, choice.value, choice.text)))
let message = new builder.Message(session).addAttachment(card);
builder.Prompts.choice(session, message, choices);
break;
case 'text':
default:
session.send(sentence.value)
break;
}
})
}
}
const generatenextAction = (actions) => {
return (session, args, next) => {
const response = args.response;
actions.map(action => {
if (action.result == response.entity) {
session.beginDialog(action.action);
}
})
}
}
const generateWaterfallSteps = (steps) => {
let waterfall = [];
steps.forEach(step => {
waterfall.push(generateSignleStep(step.data));
if (step.next) {
waterfall.push(generatenextAction(step.next));
}
});
return waterfall;
}
var bot = new builder.UniversalBot(connector);
const jsonobj = JSON.parse(json);
jsonobj.forEach(dialog => {
bot.dialog(dialog.name, generateWaterfallSteps(dialog.steps))
.triggerAction({
matches: new RegExp(dialog.name, "g")
})
});
The result is:

angular2 - tabs content load it from local json file

I am working on angular 2 Tabs component.
Currently i am following below Plunker example
Angular 2 Tabs
I need to make Tabs dynamic by reading the Local JSON file.
My JSON
[
{
"id": "1",
"name": "General",
"content": [
{
"header": "Basic Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
},
{
"id": "2",
"name": "Additional info",
"content": [
{
"header": " Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
}
]
Service.ts
export class DashboardService{
private _url: string = "assets/sample.json";
constructor( private _http: Http){}
getRecords(){
return this._http.get(this._url)
.map((response:Response) => response.json())
.catch(this._errorHandler);
}
_errorHandler(error: Response){
console.error(error);
return Observable.throw(error || "Server Error");
}
}
Component.ts
export class DynamicTabsComponent implements OnInit{
records = [];
errorMsg: string;
constructor(private _dashboardService: DashboardService) { }
ngOnInit() {
this._dashboardService.getRecords()
.subscribe(
resGetRecords => this.records = resGetRecords,
resRecordsError => this.errorMsg = resRecordsError
);
}
}
Now how to read it in the component file.
here in tab link, i am expecting is
Additional info
General
Description required with header and label.
Any help would be appreciated.
You do an *ngFor on your json to display the tabs:
<tabs>
<tab *ngFor="let tab of tabs" tabTitle="{{tab.name}}">
<div>{{tab.content[0].header}}</div>
<div>{{tab.content[0].contents[0].label}}</div>
</tab>
</tabs>
You declare your json into the component or import it from outside:
class App {
tabs = [
{
"id": "1",
"name": "General",
"content": [
{
"header": "Basic Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
},
{
"id": "2",
"name": "Additional info",
"content": [
{
"header": " Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
}
];
}
Working fork of your plunker here
If it's a local JSON file, why are you making http calls ?
To read a JSON file, simply do
let jsonFile = require('relative/path/to/json/file.json')
And it should load your JSON file.

Use Backgrid SelectFilter with JSON from API

I am having problems binding data to my Backgrid's SelectFilter (dropdown).
Here is the code that is not working:
// Create a Backbone Model
var OccupationCategoryModel = Backbone.Model.extend({
defaults: {
Prefix: "",
Title: ""
},
idAttribute: "Prefix",
urlRoot: '/api/occupationcategory',
parse: function (response) {
return {
'Title': response.Title,
'Prefix': response.Prefix
};
}
});
// Create a Backbone Collection for the dropdown list
var OccupationCategoryList = Backbone.Collection.extend({
model: OccupationCategoryModel,
url: "/api/occupationcategory",
mode: "client", // page entirely on the client side
parse: function (response) {
return response;
}
});
// Get a fresh data collection
var _categories = new OccupationCategoryList();
// Create the 'Select filter' dropdown
var categoryFilter = new Backgrid.Extension.SelectFilter({
className: "backgrid-filter form-control",
collection: somePageableCollectionNotFoundInThisCode,
field: "OccupationID", // this 'field' is found in 'somePageableCollectionNotFoundInThisCode'
selectOptions: _.union([{ label: "All", value: null }],
_.map(_categories, function (o) { return { label: o.Title, value: o.Prefix }; })) // this does not work :(
});
// fetch Occupation Categories from API - this works!
_categories.fetch({
ajaxSync: true,
success: function () {
console.log(_categories.models); // => 22 items (collection has been populated and verified)
}
});
I can verify the data is in the collection correctly (see the console.log statement), but I cannot get the data into the Select-Filter (dropdown).
If I use a static JSON list (like all the 'Hello World' examples for this online) it works, like this:
// This static list works but is un-desirable. We want to use the database. Dont ask why.
var _categories = [
{ "Prefix": "17", "Title": "Architecture and Engineering" }
, { "Prefix": "27", "Title": "Arts, Design, Entertainment, Sports, and Media" }
, { "Prefix": "37", "Title": "Building and Grounds Cleaning and Maintenance" }
, { "Prefix": "13", "Title": "Business and Financial Operations" }
, { "Prefix": "21", "Title": "Community and Social Services" }
, { "Prefix": "15", "Title": "Computer and Mathematical" }
, { "Prefix": "47", "Title": "Construction and Extraction" }
, { "Prefix": "25", "Title": "Education, Training, and Library" }
, { "Prefix": "45", "Title": "Farming, Fishing, and Forestry" }
, { "Prefix": "35", "Title": "Food Preparation and Serving Related" }
, { "Prefix": "29", "Title": "Healthcare Practitioners and Technical" }
, { "Prefix": "31", "Title": "Healthcare Support" }
, { "Prefix": "49", "Title": "Installation, Maintenance, and Repair" }
, { "Prefix": "23", "Title": "Legal" }
, { "Prefix": "19", "Title": "Life, Physical, and Social Science" }
, { "Prefix": "11", "Title": "Management" }
, { "Prefix": "43", "Title": "Office and Administrative Support" }
, { "Prefix": "39", "Title": "Personal Care and Service" }
, { "Prefix": "51", "Title": "Production" }
, { "Prefix": "33", "Title": "Protective Service" }
, { "Prefix": "41", "Title": "Sales and Related" }
, { "Prefix": "53", "Title": "Transportation and Material Moving" }
];
Just for giggles, here is the raw JSON response from our web API:
[{"Prefix":"17","Title":"Architecture and Engineering Occupations"},{"Prefix":"27","Title":"Arts, Design, Entertainment, Sports, and Media Occs"},{"Prefix":"37","Title":"Building and Grounds Cleaning and Maintenance Occs"},{"Prefix":"13","Title":"Business and Financial Operations Occupations"},{"Prefix":"21","Title":"Community and Social Services Occupations"},{"Prefix":"15","Title":"Computer and Mathematical Occupations"},{"Prefix":"47","Title":"Construction and Extraction Occupations"},{"Prefix":"25","Title":"Education, Training, and Library Occupations"},{"Prefix":"45","Title":"Farming, Fishing, and Forestry Occupations"},{"Prefix":"35","Title":"Food Preparation and Serving Related Occupations"},{"Prefix":"29","Title":"Healthcare Practitioners and Technical Occupations"},{"Prefix":"31","Title":"Healthcare Support Occupations"},{"Prefix":"49","Title":"Installation, Maintenance, and Repair Occupations"},{"Prefix":"23","Title":"Legal Occupations"},{"Prefix":"19","Title":"Life, Physical, and Social Science Occupations"},{"Prefix":"11","Title":"Management Occupations"},{"Prefix":"43","Title":"Office and Administrative Support Occupations"},{"Prefix":"39","Title":"Personal Care and Service Occupations"},{"Prefix":"51","Title":"Production Occupations"},{"Prefix":"33","Title":"Protective Service Occupations"},{"Prefix":"41","Title":"Sales and Related Occupations"},{"Prefix":"53","Title":"Transportation and Material Moving Occupations"}]
How can I get the successful 'fetch' to populate my Select-Filter? Shouldn't it be automatic?

MongoDB, NodeJS: updating an embedded document with new members

Using: MongoDB and native nodeJS mongoDB driver.
I'm trying to parse all the data from fb graph api, send it to my API and then save it to my DB.
PUT handling in my server:
//Update user's data
app.put('/api/users/:fbuser_id/:category', function(req, res) {
var body = JSON.stringify(req.body);
var rep = /"data":/;
body = body.replace(rep, '"' + req.params.category + '"' + ':');
req.body = JSON.parse(body);
db.fbusers.update({
id: req.params.fbuser_id
}, {
$set: req.body
}, {
safe: true,
multi: false
},
function(e, result) {
if (e) return next(e)
res.send((result === 1) ? {
msg: 'success'
} : {
msg: 'error'
})
});
});
I'm sending 25 elements at a time, and this code just overrides instead of updating the document.
Data I'm sending to the API:
{
"data": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Basically my API changes "data" key from sent json to the category name, f.e.:
PUT to /api/users/000/likes will change the "data" key to "likes":
{
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Then this JSON is put to the db.
Hierarchy in mongodb:
{
"_id": ObjectID("556584c8e908f0042836edce"),
"id": "0000000000000",
"email": "XXXX#gmail.com",
"first_name": "XXXXXXXX",
"gender": "male",
"last_name": "XXXXXXXXXX",
"link": "https://www.facebook.com/app_scoped_user_id/0000000000000/",
"locale": "en_US",
"name": "XXXXXXXXXX XXXXXXXXXX",
"timezone": 3,
"updated_time": "2015-05-26T18:11:59+0000",
"verified": true,
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
....and so on
}
]
}
So the problem is that my api overrides the field (in this case "likes") with newly sent data, instead of appending it to already existing data document.
I am pretty sure that I should be using other parameter than "$put" in the update, however, I have no idea which one and how to pass parameters to it programatically.
Use $push with the $each modifier to append multiple values to the array field.
var newLikes = [
{/* new item here */},
{/* new item here */},
{/* new item here */},
];
db.fbusers.update(
{ _id: req.params.fbuser_id },
{ $push: { likes: { $each: newLikes } } }
);
See also the $addToSet operator, it adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.