How can i access to 'download_url' in json using vuejs - json

i want to get 'tags' and 'download url' inside meta, i cannot access to 'download_url' in json how i can do it, as a backend i am using wagtail cms, and is it good to use vue js with wagtail cms (headless cms)
<template>
<div>
<div>
<b-card-group deck v-for="item in results" :key="item.id">
<b-card
>
<b-card-text>
<div v-for="block in item.body" :key="block.id">
<div v-if="block.type == 'heading'">
<h2>{{block.value}}</h2>
</div>
<div v-if="block.type == 'image'">
<img :src="'http://127.0.0.1:8000/api/v2/images/' + block.value">
</div>
<div v-if="block.type == 'paragraph'">
<h2 v-html="block.value">{{block.value}}</h2>
</div>
</div>
</b-card-text>
>
</b-card>
</b-card-group>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Home',
data () {
return {
results: null
}
},
mounted () {
axios.get('http://127.0.0.1:8000/api/v2/pages/?type=news.NewsPage&fields=intro,body,image_thumbnail')
.then((response) => (
this.results = response.data.items
))
}
}
</script>
here is json api. i accessed till id of image and do not know what to do next
{
"id": 3,
"meta": {
"type": "wagtailimages.Image",
"detail_url": "http://localhost/api/v2/images/3/",
"tags": [
"gadget",
"phone",
"samsung"
],
"download_url": "/media/original_images/affordable_new_9-7-inch_ipad_group_fan2_1_1.png"
},
"title": "affordable_new_9-7-inch_ipad_group_fan2 1 (1).png",
"width": 528,
"height": 357
}

Assuming that response.data.items is the json you showed above, you can extract just what you want from there. Right now, your component has the whole response.data.items in this.response. So if you want all of it there, keep that.
You can store the 'tags' and 'download url' to your component by adding two new pieces of data ie add them to your data:
data () {
return {
results: null,
tags: null,
downloadUrl: null
}
... and then set those in your response block from the request's response like this.
mounted () {
axios.get('http://127.0.0.1:8000/api/v2/pages/?type=news.NewsPage&fields=intro,body,image_thumbnail')
.then((response) => (
this.results = response.data.items
this.tags = response.data.items.meta.tags
this.downloadUrl = response.data.items.download_url
))
}
When dealing with nested response objects like this, it can help to make a local variable with the data and add it that way. Also, if you dont need the whole response, you can avoid storing it and just store the data from the response that you want to your component here. If you wanted to get something from your this.response, you're going to have to go deep into it. It would be cleaner to just pull out only what you need, and then use it in your code with just one {{myStuffIPulledOut}} vs {{response.thingIWantBefore.actualThing.}}

Related

How to create autocomplete box using vue.js?

I am new at Vue, now I am creating simple search app (using Vue.js cdn).
I want to append suggestion bar which contains all user id's from fake JSON server, for example if I write into search bar 1, I want to append only user which id is 1, and then I click to that user id I want to send another request to receive only this user info.
I am stuck, how I can solve this?
var app = new Vue({
el: '#app',
data: {
message: '',
searchKey:'',
result:[]
},
methods:{
async getData() {
// GET request using fetch with async/await
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${this.searchKey}`);
const data = await response.json()
this.result = data
},
},
created(){
this.getData()
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.14/vue.js"></script>
<div id="app">
<div class="search-area">
<div class="header-wrapper">
<h1>Tag Search</h1>
</div>
<div class="search-bar-custom">
<input placeholder="Search tags" v-model="searchKey" #keyup="getData" />
<div class="suggetions">
<ul class="suggestions" id="suggestions">
<li><h1>suggetion id</h1></li>
</ul>
</div>
</div>
</div>
</div>
You are on the right way, but, there are some issues about your logic here, for json-server you need to use the Operator _like (https://github.com/typicode/json-server#operators) to retrieve or filter data depending the column or property, so, your getData method must be like this:
async getData() {
// GET request using fetch with async/await
const response = await fetch(
`https://jsonplaceholder.typicode.com/users?name_like=${this.searchKey}`
);
const data = await response.json();
this.result = data;
},
You can change the property or column, in example username_like or id_like.
Finally, you need to show the results, so, change your template:
<ul class="suggestions" id="suggestions">
<h1 v-for="item in result" #mousedown="show(item)">
{{ item.id }} | {{ item.name }}
</h1>
</ul>
Pay attention on #mousedown="show(item)", when user click on some result, this action will display the data about user, for that, we need to create a new method called show and pass the item:
show(item) {
alert(JSON.stringify(item, null, 2));
}
You can look how it works here: https://codepen.io/riateam/pen/ExNrGOE?editors=1010

How to make filters in Vue.js based on element list?

Introdution
Hi, I'm working on private project "Avatar databse" in Vue.js framework. App shows them based on data() elements:
data() {
return {
avatars: [
{
name: "Butterfly Blue",
tags: [
"animal",
"butterfly",
"blue"
]
},
{
name: "Butterfly Green",
tags: [
"animal",
"butterfly",
"green"
]
},
{
name: "Deer Shining",
tags: [
"animal",
"deer"
]
},
What I want
I would like to make search engine based on tags. Most of help pages are about previous Vue versions or search is based on name - one element. I want to search in tag list not single name string.
Without search engine, every avatar renders correctly
Current component code
template:
<div class="row">
<div v-for="image in avatars" :key="filteredData" class="col-6 col-sm-4 col-md-3 col-lg-2 my-2">
<img v-bind:src="imgSource(image.name)" v-bind:alt="image.name" class="img-fluid" :class="avatarClass" />
<a :href="imgSource(image.name)" :class="downloadClass"><span class="icon-download-alt"></span></a>
<p class="h5 text-center py-1">{{ image.name }}</p>
<p v-for="tag in image.tags" v-bind:key="tag" :class="tagClass">{{ tag }}</p>
</div>
</div>
computed()
avatarClass() {
return 'avatar';
},
tagClass() {
return 'tag';
},
downloadClass() {
return 'download';
},
filteredData() {
if (this.search == '') {
return this.avatars;
} else {
return this.avatars.filter(obj => {
return obj.name.toLowerCase().includes(this.search.toLowerCase());
});
};
},
Of course filterind related thigs doesn't work. And there's my question...
How to make working, tag list based, search engine?
(Based on my project.)
It's small changes to the search that has been done. I've made a codesandbox where it's working:
https://codesandbox.io/s/festive-napier-3jk52
filteredData() {
if (this.search == "") {
return this.avatars;
} else {
return this.avatars.filter(obj => {
return obj.tags.indexOf(this.search.toLowerCase()) !== -1;
});
}
}
It's pretty simple. There's a search data variable, where you can put in the tag you want to search for. Right now it only searched for the whole tag, and has to match a tag fully, but this can be changed if you want people to be able to search for "anim", and then the avatars with the "animal" tag should be shown.
You enter butterfly in your search field and only Butterfly Blue and Butterlfy Green should appear?
Instead of
return this.avatars.filter(obj => {
return obj.name.toLowerCase().includes(this.search.toLowerCase());
});
try this:
return this.avatars.filter(avatar => avatar.tags.includes(this.search.toLowerCase()));

Show MongoDB info in HTML

I'm working on a website using a MEAN stack, and now I am trying to show some MongoDB data in my HTML pages by using Angular. But I don't seem to get it done.
This is the data in MongoDB I want to show in my HTML
{
"badkamer" : {
"block1" : {
"title" : "Badkamer",
"content" : "string"
}
}
}
This is the Angular function retrieving the data:
app.controller('cityCtrl', function($scope,$http){
$scope.specials = function(){
$scope.special = [];
$http.get('/specialdata').then(function(d){
$scope.special = d.data;
console.log(d.data);
},function(err){
console.log(err);
});
};
});
This is where I want it to show in my HTML:
<div ng-controller="cityCtrl" ng-init="specials()" ng-bind="special">
<div class="title">{{special.badkamer.block1.title}}</div>
<p>{{special.badkamer.block1.content}}</p>
</div>
</div>
When i console.log(d.data), I get this:
[Object]
0: Object
badkamer: Object
block1: Object
content: "Text",
title: "Badkamer"
But when I try it like this, the bind option shows all the data at once in my HTML. How can I get it working by using the Angular {{}} tags?
From the console.log, you can see that its an array, so you will need to use index, like this,
<div ng-controller="cityCtrl" ng-init="specials()" ng-bind="special">
<div class="title">{{special[0].badkamer.block1.title}}</div>
<p>{{special[0].badkamer.block1.content}}</p>
</div>
</div>
or change the code in controller.,
$scope.special = d.data[0];

How to implement nested data form in angular2

Here is Json schema :
{
"_id" : ObjectId("59031d77fd5e1c0b3c005d15"),
"resume_data" : {
"work_experience" : [
{
"company" : "example",
"website" : "example.com",
"position" : "Internship",
"highlights" : "Learn To Create API In Laravel Framework. and also Learn Angular 2 for Front end Development.",
"project_experience" : [
{
"projectName" : "Fb Project",
"teamMember" : "5",
"technology" : "PHP,Laravel-5,Angular-2,MongoDb",
"projectPosition" : "Back-end Developer"
}
]
}
]
}
}
Here is image:
I have reference of this answer but i don't know about nested form data. can anyone explain how to implement it.
Here is your code, which sets the data you are receiving from backend, here I have stored it in a variable data.
Please notice, this is a shortened version of your form, but the basics are there, you only need to add the few missing properties in corresponding form arrays.
The build of the empty form looks is just a FormArray named work_experience matching your json structure:
this.myForm = this.fb.group({
work_experience: this.fb.array([])
})
We add the fields when you are receiving the data, call a function called setWorkExperience in the callback when receiving data:
setWorkExperience(){
// get the formarray
let control = <FormArray>this.myForm.controls.work_experience;
// iterate the array 'work_experience' from your JSON and push new formgroup with properties and the inner form array
this.data.work_experience.forEach(x => {
// add the rest of your properties also below
control.push(this.fb.group({company: x.company, project_experience: this.setFormArray(x)}))
})
}
setFormArray is called from the previous function, where we patch the data with from project_experience to the inner form array:
setFormArray(x) {
// create local array which is returned with all the values from the 'project_experience' from your JSON
let arr = new FormArray([])
x.project_experience.map(y => {
// add the rest of your properties below
arr.push(this.fb.group({projectName: y.projectName}))
})
return arr;
}
The template would then look like this:
<form [formGroup]="myForm">
<!-- Outmost array iterated -->
<div formArrayName="work_experience">
<div *ngFor="let a of myForm.get('work_experience').controls; let i=index">
<h3>COMPANY {{i+1}}: </h3>
<div formGroupName="{{i}}">
<label>Company Name: </label>
<input formControlName="company" /><span><button (click)="deleteCompany(i)">Delete Company</button></span><br><br>
<!-- inner formarray iterated -->
<div formArrayName="project_experience">
<div *ngFor="let b of myForm.controls.work_experience.controls[i].controls.project_experience.controls; let j=index">
<h4>PROJECT {{j+1}}</h4>
<div formGroupName="{{j}}">
<label>Project Name:</label>
<input formControlName="projectName" /><span><button (click)="deleteProject(a.controls.project_experience, j)">Delete Project</button></span>
</div>
</div>
<button (click)="addNewProject(a.controls.project_experience)">Add new Project</button>
</div>
</div>
</div>
</div>
</form>
In the template you can see the buttons for add and delete of projects and companies. Adding and deleting companies are straightforward, where initCompany() returns a formGroup:
deleteCompany(index) {
let control = <FormArray>this.myForm.controls.work_experience;
control.removeAt(index)
}
addNewCompany() {
let control = <FormArray>this.myForm.controls.work_experience;
control.push(this.initCompany())
}
In the add project we pass as parameter from the template the current formArray control, to which we just push a new FormGroup:
addNewProject(control) {
control.push(this.initProject())
}
In the delete function we pass the current formarray as well as the index of the project we want to delete:
deleteProject(control, index) {
control.removeAt(index)
}
That should cover pretty much everything.
Plunker
Please Check it Out This
Plunker Here
Json Store Like This
{
"name": "",
"work_experience": [
{
"name": "asdasd",
"project_experience": [
{
"Project_Name": "asdasdasd"
},
{
"Project_Name": "asdasdasd"
}
]
}
]
}

Dojo Grid reload data file upon button click

I know there maybe similar questions out there, but I still cannot find the answer. Much appropriate anyone who can help me.
There are 5 departments, and each department has 4 products. So I created 5 buttons and 4 tabs, each tab contains a grid. By default the department A is loaded, user can switch tabs to see different products information from this department. By click another button B, department B's information will loaded to all 4 tabs.
Click each button will send a ajax request to the back end PHP code, PHP will read XML file do calculation and write data to "data\productA.json", "data\productB.json" , "data\productC.json" , "data\productD.json" files, respect to product A to product D for that specific department. Note that the first tab always read from "data\product A" file, no matter which button you clicked, same for other tabs.
Then the JavaScript will read from the "data\product?.json" file and present data in the grid.
When the page loads, first department's information is correctly loaded into the grid. However, if I change to another department (click button), the grid won't reload data from the json files.
Here is JS part:
dojo.addOnLoad(function() {
//init the first main column when load the page.
getDepartmentA();
var layout = [[
new dojox.grid.cells.RowIndex({ width: 5 }),
{name: 'Name', field: 'name'},
{name: 'Count', field: 'count'},
{name: 'Percent', field: 'percent'}
]];
var store = new dojo.data.ItemFileReadStore( { url: "data/productA.json" } );
var grid = new dojox.grid.DataGrid( { store: store, rowsPerPage: 200, style: "height:600px; width:874px;", structure: layout},
dojo.byId("grid1"));
grid.startup();
dojo.connect( dijit.byId("column3"),"onShow", dojo.partial( createGrid, "3") );
dojo.connect( dijit.byId("column4"),"onShow", dojo.partial( createGrid, "4") );
dojo.connect( dijit.byId("column5"),"onShow", dojo.partial( createGrid, "5") );
});
function getDepartmentA() {
dojo.xhrGet( {
url: "department_A_process.php",
handleAs: "json",
load: function(response) {
var tempgrid = grids[0];
var tempresponse = eval("("+response+")");
var tempstore = new dojo.data.ItemFileReadStore({url: "data/productA.json" }); //updated store!
var tempModel = new dojox.grid.data.DojoData(null, tempstore, {query:{productName:'*'}, clientSort: true});
tempgrid.setaModel(tempModel);
tempgrid.refresh();
console.dir(response); // Dump it to the console
}
});
}
function createGrid( id ) {
console.log("Calling createGrid function now!");
var layout = [[
new dojox.grid.cells.RowIndex({ width: 5 }),
{name: 'Name', field: 'name'},
{name: 'Count', field: 'count'},
{name: 'Percent', field: 'percent'}
]];
if (! grids[id] ) {
if (id =="1"){
var store = new dojo.data.ItemFileReadStore( { url: "data/productA.json" } );
console.log( "I am in tab1");
} else if (id =="3"){
var store = new dojo.data.ItemFileReadStore( { url: "data/productB.json" } );
console.log( "I am in tab3");
} else if (id =="4"){
var store = new dojo.data.ItemFileReadStore( { url: "data/productC.json" } );
console.log( "I am in tab4");
} else if (id =="5"){
var store = new dojo.data.ItemFileReadStore( { url: "data/productD.json" } );
console.log( "I am in tab5");
}
var grid = new dojox.grid.DataGrid( { store: store, rowsPerPage: 200, style: "height:600px; width:874px;", structure: layout},
dojo.byId("grid" + id ));
grid.startup();
grids[id] = grid;
console.log( grid );
}
}
My index page is like:
<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" doLayout="false">
<div id="column1" dojoType="dijit.layout.ContentPane" title="Label by Brand" selected="true">
<h1>Label by Brand</h1>
<div class="partsContainer">
<div id="grid1" class="gridContainer">
</div>
</div>
</div>
<div id="column3" dojoType="dijit.layout.ContentPane" title="Session Types">
<h1>Session Types</h1>
<div class="partsContainer">
<div id="grid3" class="gridContainer">
</div>
</div>
</div>
<div id="column4" dojoType="dijit.layout.ContentPane" title="Labels by Session">
<h1>Labels by Session</h1>
<div class="partsContainer">
<div id="grid4" class="gridContainer">
</div>
</div>
</div>
<div id="column5" dojoType="dijit.layout.ContentPane" title="Monthly Report">
<h1>Monthly Report</h1>
<div class="partsContainer">
<div id="grid5" class="gridContainer">
</div>
</div>
</div>
</div>
The JSON file looks like:
{
identifier: "productName",
label: "productName",
items: [
{ "productName" : "p1", "count" : 3362, "percent" : "32.8" },
{ "productName" : "p2", "count" : 421, "percent" : "4.1" },
{ "productName" : "p3", "count" : 526, "percent" : "5.1" },
{ "productName" : "p4", "count" : 1369, "percent" : "13.4" },
...
{ "productName" : "Total", "count" : 10242, "percent" : "100" }
]
}
Anyone can help out, how to reload the file that generated by PHP to the grid? Thank you.
I don't see any code involving a button or requesting new data for a store in your code...
To fix your issue, try adding clearOnClose:true to your store initializations. You may also need urlPreventCache:true. Firebug or any sort of net monitor will tell you if this is needed.
When the button is pressed, get the reference to the store for each grid and call store.close() then store.fetch(). This should accomplish what you are looking for by refreshing the data in the store. After this it may be necessary to call grid.render() or something similar.
One thing I should note here just to save you a possible headache later: Unless you have some sort of user hash for the directory structure and security measures in place, the way your PHP behaves by creating a single set of files for each department is likely going to result in problems with multi-user support and security issues where you can read another person's JSON responses.
Found the info here : http://livedocs.dojotoolkit.org/dojo/data/ItemFileReadStore. Search for clearOnClose for the approximate area to look for information.