The vue.resource() method and the api.json file - javascript

I'm new to vue.js and I'm confused about what to do next in the program. I want to add a new view page to collect customer information (see code below). I don't know how to write the function after I click the "confirm" button. I think I should go the DataService.js file to get the data or update the rules.
Here is the url for the project:
https://coding.net/u/benbenshi/p/vue-admin-test/git
// baseConfig.vue
<template>
<div class="system-base">
<el-input type="text">
<template slot="prepend">userInput:</template>
</el-input>
</div>
<div>
<el-button #click="somefunction">confirm</el-button>
</div>
</template>
<script>
import dataservice from '../../services/DataService'
export default {
components: {},
data () {
return {}
},
computed: {},
methods: {
// what should I do here? Should I write some function to handle the confirm event?
},
}
</script>
Right now I've got an api.json file with a structure like this: should I write the function in the dataServices.js file based on the API offered in the api.json file?
//api.json
{
"id": "",
"name": "api",
"description": "",
"order": [],
"folders": [],
"timestamp": 1234567,
"owner": "1234567",
"public": false,
"requests": [
// a lot of request api here.
]
}
Any help will be appreciated!

You can take a reference from the vue-hackernews-2.0 code, You can do whatever action you want to do, and than call this.$router.replace("/your/path") to redirect to desired page. Here is the stripped code from the repo:
methods: {
loadItems (to = this.page, from = -1) {
this.loading = true
this.$store.dispatch('FETCH_LIST_DATA', {
type: this.type
}).then(() => {
this.$router.replace(`/${this.type}/1`)
return
this.loading = false
})
}

Related

VueJS and nested v-for: How to get endpoint data through each loop?

I am using VUEJS to build a single page application. I have a single file component that gets some data from an API (using Axios) and uses v-for to render out a list like so:
<template>
<div>
<ul>
<li v-for="division in divisions" :key="division.id_PK">
{{ division.c6code }} - XXX
</li>
</ul>
</div>
</template>
props: {
country: {
type: Object,
required: true
}
},
data() {
return {
divisions: [],
},
methods: {
async getDivisions() {
const divisions = await APIService.getDivisions(
this.country.igpeSID_FK
)
this.divisions = divisions
},
}
An example of the API data source looks like /getDivisions/800001:
{
"status": 200,
"data": [
{
"id_PK": 205891,
"igpeSID_FK": 800001,
"c6code": "AB-CDE"
},
{
"id_PK": 205890,
"igpeSID_FK": 800001,
"c6code": "FG-HIJ"
},
{
"id_PK": 205889,
"igpeSID_FK": 800001,
"c6code": "KL-MNO"
},
{
"id_PK": 205888,
"igpeSID_FK": 800001,
"c6code": "PQ-RST"
},
{
"id_PK": 205887,
"igpeSID_FK": 800001,
"c6code": "WX-YZA"
}
]
}
The rendered UI looks like so:
Now, there is another API endpoint that contains additional data that I need to put in place of the "XXX" placeholder shown above. That additional data source has a property called name and contains the actual division name which was not included in the /getDivisions API (only the associated property id_PK is provided).
Question: How can I get this name for each division?
An example of this endpoint that contains the additional data is: /getDivisionNameById/{id_PK} where id_PK is the parameter I need to pass to it from the getDivisions data shown above. So, for example, if I pass 205891 to the /getDivisionNameById/205891 I get back data that looks like so:
Example /getDivisionNamesById/205891:
{
"status": 200,
"data": [
{
"P_uniqueID": 16919,
"isoGeoDivisionEntry_FK": 205891,
"name": "ZABUL",
"lang": "fa"
},
{
"P_uniqueID": 16918,
"isoGeoDivisionEntry_FK": 205891,
"name": "ZABUL",
"lang": "ps"
}
]
}
I am thinking that I need to create a function that somehow creates a new array of names that I could then loop through in yet another v-for in my original template like so:
<li v-for="division in divisions" :key="division.id_PK">
{{ division.c6code }} - <span v-for="divName in divisionNames" :key="division.id_PK">{{divName.name}}</span>
</li>
async getDivisionNameById(id_PK) {
const name = await APIService.getDivisionNameById(id_PK)
this.divNames.push(name)
}
Obviously, I don't know what I am doing there...
Codesandbox with data:
https://codesandbox.io/s/intelligent-wind-21w35?file=/src/getDivisionNamesById.json
You have to query the data first before rendering the content.
You could fetch all the data in onMounted hook.
Thats a good place for a computed property.
Edit this example as needed depending on how you call your APIs.
You could call both API endpoints in the mounted lifecycle-hook of the component. Included this with a simple timeout to simulate the data coming in at different times.
About the secondary API call(s) where you get the name-data: As you've already said, loop through the IDs and make the API calls. In this case you'd need to wait for the result of your first API call and then use those ID's it returns to make the second API call(s). Maybe this will help you with the await/asyc/then stuff:
How to use async/await in Vue.js?
<template>
<div class="hello">
<ul>
<li v-for="(division, index) in fullList" :key="index">
{{ division }}
</li>
</ul>
</div>
</template>
<script>
import divisions from "#/getDivisionsEntries.json";
import divisionNames from "#/getDivisionNamesById.json";
export default {
name: "DivisionsList",
data() {
return {
divisions: divisions.data,
divisionNames: null,
};
},
mounted() {
setTimeout(() => {
this.divisions = divisions.data;
}, 1000);
setTimeout(() => {
this.divisionNames = divisionNames.data;
}, 3000);
},
computed: {
fullList: function () {
let combinedArr = [];
for (var divi of this.divisions) {
var divNameData = this.divisionNames?.find(
(x) => x.isoGeoDivisionEntry_FK === divi.id_PK
);
if (divNameData !== undefined) {
combinedArr.push(`${divi.c6code} - ${divNameData.name}`);
}
}
return combinedArr;
},
},
};
</script>

Programmatically create Gatsby pages from Contentful data

I am looking for help with GatsbyJS and Contentful. The docs aren't quite giving me enough info.
I am looking to programmatically create pages based on contentful data. In this case, the data type is a retail "Store" with a gatsby page at /retail_store_name
The index.js for each store is basically a couple of react components with props passed in e.g. shop name and google place ID.
Add data to contentful. Here is my example data model:
{
"name": "Store"
"displayField": "shopName",
"fields": [
{
"id": "shopName",
"name": "Shop Name",
"type": "Symbol",
"localized": false,
"required": true,
"validations": [
{
"unique": true
}
],
"disabled": false,
"omitted": false
},
{
"id": "placeId",
"name": "Place ID",
"type": "Symbol",
"localized": false,
"required": true,
"validations": [
{
"unique": true
}
],
"disabled": false,
"omitted": false
}
}
I've added the contentful site data to gatsby-config.js
// In gatsby-config.js
plugins: [
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: `your_space_id`,
accessToken: `your_access_token`
},
},
];
Query contentful - I'm not sure where this should happen. I've got a template file that would be the model for each store webpage created from contentful data.
As mentioned this is just some components with props passed in. Example:
import React, { Component } from "react";
export default class IndexPage extends Component {
constructor(props) {
super(props);
this.state = {
placeId: "",
shopName: "",
};
}
render (){
return (
<ComponentExampleOne shopName={this.state.shopName} />
<ComponentExampleTwo placeId={this.state.placeId} />
);
}
I'm really not sure how to go about this. The end goal is auto publishing for non-tech users, who post new stores in Contentful to be updated on the production site.
You can create pages dynamically at build time and to do that you need to add some logic to the gatsby-node.js file. Here is a simple snippet.
const path = require('path')
exports.createPages = ({graphql, boundActionCreators}) => {
const {createPage} = boundActionCreators
return new Promise((resolve, reject) => {
const storeTemplate = path.resolve('src/templates/store.js')
resolve(
graphql(`
{
allContentfulStore (limit:100) {
edges {
node {
id
name
slug
}
}
}
}
`).then((result) => {
if (result.errors) {
reject(result.errors)
}
result.data.allContentfulStore.edges.forEach((edge) => {
createPage ({
path: edge.node.slug,
component: storeTemplate,
context: {
slug: edge.node.slug
}
})
})
return
})
)
})
}
the createPages that was exported is a Gatsby Node API function you can find the complete list in the docs here.
For the query allContentfulStore it's called like that because your contentType name is store the gatsby query will be allContentful{ContentTypeName}.
Finally, I created a youtube video series explaining how you can build a Gatsby website with Contentful. You can find it here
I hope this answer your question.
Cheers,
Khaled

Operating on JSON returned from http.get in Angular 4.3

In my my, I am attempting to serve dynamic form controls via JSON to a form builder similar to the dynamic forms tutorial at angular.io. I am having trouble operating on JSON data returned from an http.get() request. I can console.log the whole object, but if I try to log a sub-object, I get "undefined" in the console.
Here is my component file:
export class TestComponent implements OnInit {
dataSource: Observable<any>;
questions: QuestionBase<any>[] = [];
results: QuestionBase<any>[] = [];
constructor(private http: HttpClient) {
this.dataSource = this.http.get('/questions');
}
ngOnInit() {
this.dataSource.subscribe(
data => {
this.results = data['contactInfo'];
console.log(this.results[0].controlType);
this.results.forEach((item: QuestionBase<any>) => {
if(item.controlType == 'text') {
console.log(item.controlType);
this.questions.push(new TextQuestion(item));
}
else if(item.controlType == 'dropdown') {
console.log(item.controlType);
this.questions.push(new DropdownQuestion(item));
}
});
console.log(this.questions);
},
err => {
console.log("Cannot get JSON data. Error Code: %s, URL: %s",
err.status, err.url)
},
() => console.log('Done')
);
}
}
In the data => {} callback, if I console.log(request), the console displays the entire object just fine. I can even read sub-objects in the template. But, if I try to console.log or do any other thing with sub-objects as in the code above, e.g. the forEach() method, I get "undefined" on the console. What am I doing wrong?
Edit: Here is the JSON snippet:
{
"contactInfo": [
{
"key": "firstName",
"globalLabel": "First Name",
"controlType": "text",
"required": "true",
"order": "1"
},
{
"key": "lastName",
"globalLabel": "Last Name",
"controlType": "text",
"required": "true",
"order": "2"
},
{
"key": "streetAddress",
"globalLabel": "Street Address",
"controlType": "text",
"required": "true",
"order": "3"
}, ...}]
Edit #2 I had failed to restart my Node server after updating the JSON file to read "controlType" over an earlier version that used simply "type." I figured the server would automatically serve the newly edited and saved file, but it seems as though one must restart the server in order to do this. ISSUE CLOSED

Trying to access my TypeScript class properties so that I can display in HTML

I am trying to redevelop a project I am working on into Angular 2 from Angular 1. Currently I am using Ionic to build it as it is used on iOS. This redevelopment is my first interaction with TypeScript at all.
So far I have been able to get most of what I need done. But now my issue is that I want to access a property of my class and display it in the HTML code but only after it has been set, this way I wouldn't run into errors. But my code or at least Ionic says that the property is undefined even if I use the ngOnInit or ngAfterContentInit functions to try and do this.
I may be going about this code the wrong way but I would like to ask how to access these properties so that I can display them in the HTML as *ngFor= 'let e of EventInfo' then {{e.eventName}}. Please help me out. I will continue to search the previous questions to hopefully find some inspiration to answer my question.
I will add my class code so far below.
To add some more information, the e.eventName I am planning to use on a menu that toggles out and it will display the information I want from eventInfo.
For the code below, I also added what pullJson.getMondayJson looks like.
This is what eventInfo initially looked like when I tried it out.
this.eventInfo = [{rType: this.mondayJson.agendaEvents[0].rowType, eventName:this.mondayJson.agendaEvents[0].eventName, startTime:this.mondayJson.agendaEvents[0].startTime, endTime:this.mondayJson.agendaEvents[0].endTime}];
#Component({
selector: 'center-panel',
host: {'(window:scroll)': 'track($event)'},
templateUrl: 'center-panel.html'
})
export class CenterPanel {
mondayJson;
tuesdayJson;
wednesdayJson;
pages: Array<{title: string}>;
eventInfo: Array<{eventName: string, startTime: any, endTime: any}>;
public constructor(public pullJson:PullJson, public menu: MenuController, locationA2:Location) {
this.pages = [
{ title: 'CenterPanel'},
{ title: 'RightPanel'}
];
pullJson.getMondayJson
.subscribe(
getMondayJson => this.mondayJson = {
dayOfWeek: getMondayJson.dayOfWeek.toUpperCase(),
agendaEvents: getMondayJson.agendaEvents
},
console.error,
() => console.log('Completed HTTP for Monday!!')
);
}
this.getMondayJson = this.http.get('https://../remote-server-file.json')
.map(response => response.json());
Someone asked me to post the template code:
<div id="{{ 'MONDAY-events-' + event.startTime }}" menuToggle class="agenda-event-container" *ngFor="let event of mondayJson.agendaEvents" (click)="event.itemClicked = !event.itemClicked">
<div class="agenda-event-row {{event.rowType}}">
<div class="time-container">
<div class="event-left-border-{{event.iconType}}">
<div class="start-time">
{{event.startTime}}
</div>
<div id="MONDAY-events-endTime" class="end-time">
{{event.endTime}}
</div>
</div>
</div>
</div>
</div>
</div>
Here is an example of what the Json files look like:
{
"rowType": "event",
"eventName": "Facilitator Training",
"iconType": "workshop",
"startTime": "8:00AM",
"endTime": "10:00AM",
"headerLocation": "Go To Brooklyn",
"locationDetails": {
"jsonGroupFile": {
"subData": "",
},
"hardcodedList": ["<b>Test:<br>New York"]
},
"subEvents": [
{
"presentationName": "",
"durationInMinutes": "120",
"speakers": "Test Person"
}
],
"images": [
{
"imageType": "hotel"
},
{
"imageType": "map"
}
],
"files": []
}

Redirection after the login succeeds or fails in loopback framework

I have recently started with loopback framework and made a simple login functionality by creating a 'customer' model inheriting from base 'User' like this:
CUSTOMER.JSON
{
"name": "customer",
"base": "User",
"idInjection": true,
"properties": {
"email":{
"type":"string",
"required":false
},
"username":{
"type":"string",
"required":false
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
CUSTOMER.JS
module.exports = function(customer){
}
I then made a entry in model-config.json like this:
"customer": {
"dataSource": "mango-database",
"public": true
}
And yes I was able to login and logout easily. I have a login screen with fields username and password. I submit this form to customers/login and as soon as it gets the login, I get a screen:
{
id: "lvrTjKBKXCFPTMFej6AyegQUFYe5mSc1BiYbROZwCBM0jqae7kZ7v8ZfGujfDGgy",
ttl: 1209600,
created: "2014-12-07T08:12:17.572Z",
userId: "5483e88b5e9cf2fe0c64dd6c"
}
Now I want that instead of this screen, I should be able to redirect user to some other page (dashboard) and if the login fails, it should go back to the login screen.
I googled up a lot on this and all i found was the suggestions to use hooks. But hooks doesn't have such event. Where do I write the redirection functionality? My guess is CUSTOMER.JS
I found the documentation quiet confusing !
Use context.res provided in a remote hook. For example:
Customer.afterRemote('create', function(context, customer, next) {
var res = context.res; //this is the same response object you get in Express
res.send('hello world');
})
Basically, you have access to request and response objects, so just respond as you would in Express. See http://expressjs.com/4x/api.html for more info.

Categories

Resources