Vue-js call object with special id - javascript

I'm a newbie in Vue-js and really need your help:
In my Django project I have 2 models: Patient and MedCard of this patient. They are connected with a Foreign Key. I want to implement such functionality: on page "Patients" I have list of patients, then when I push on someone's name I want to see his/her MedCard.
This is my code, but when I push on name I get all records for all patients from MedCard model:
Patients.vue:
<div v-for="patient in patients">
<h3 #click="openMedCard(patient.id)">{{patient.surname}} {{patient.name}}</h3>
<p>{{patient.birth_date}}</p>
</div>
<div
<MedCard v-if="med_record.show" :id="med_record.id"></MedCard>
</div>
export default {
name: 'Patient',
components: {
MedCard,
},
data() {
return {
patients: '',
med_record: {
patient: '',
show: false,
}
}
}
and methods from Patient.vue:
methods: {
openMedCard(id) {
this.med_record.patient = id
this.med_record.show = true
}
MedCard.vue:
<template>
<mu-row v-for="med_record in med_records">
<h3>Doc – {{med_record.doc.surname}}{{med_record.doc.name}}</h3>
<p>{{med_record.patient.surname}}</p>
<p>{{med_record.record}}</p>
<small>{{med_record.date}}</small>
</mu-row>
</template>
export default {
name: 'MedCard',
props: {
id: '',
},
data() {
return {
med_records: '',
}
},
methods: {
loadMedCard() {
$.ajax({
url: "http://127.0.0.1:8000/api/v1/hospital/med_card/",
type: "GET",
data: {
id: this.id,
patient: this.patient
},
success: (response) => {
this.med_records = response.data.data
}
})
}
}
}
loadMedCard() gives me info from all MedCards in JSON like this:
{
"data": {
"data": [
{
"id": 1,
"patient": {
"id": 1,
"surname": "KKK",
"name": "KKK",
"patronymic": "LLL",
"birth_date": "1999-07-07",
"sex": "F",
"phone": "no_phone",
"email": "no_email"
},
"doc": {
"id": 3,
"surname": "DDD",
"name": "DDD",
"patronymic": "DDD",
"education": "d",
"category": "2",
"sex": "m",
"phone": "no_phone",
"email": "no_email"
},
"record": "test text",
"date": "2020-06-09"
}...]
I'll be grateful for any help!

So the API returns you multiple patients's data while you're asking it for just one exact patient. There must be something wrong with the API with the filtering in first place. So you can filter your data on the client side, in your MedCard.vue component. First this component have to show data for one patient only, so the v-for="med_record in med_records" is not needed. Your med_records property can become just an object not an array:
data() {
return {
med_record: {},
}
}
And in the success resolve method of your API call you can filter only the data you need and store it in med_record
success: (response) => {
this.med_records = response.data.data.find((patient)=> { return patient.id === this.id})
}
If you want to store all the data in the med_records, then you can create computed property and apply the same filtering there.
I hope this helps.

Related

When should I use the read/writeQuery and when the read/writeFragment while working with the Apollo Cache?

I'm working with the Apollo local cache and I found that the read/writeQuery works in the same way as read/writeFragment. Both of them do the same thing and the only difference at my opinion is just that the readQuery returns an object that contains the query name as a key and the query result as a value. The readFragment returns the query result object itself.
Based on the official documentation about readQuery I could assume that it executes the query and returns the data.
About the readFragment things look the same. The only difference is that in the case of Fragment I should pass the composed ID of the required item that Apollo cache uses itself.
But the result is totally the same as in the case of readQuery except that it returns the object of values.
Here is the code example.
Sorry, there are will be a lot of cumbersome boilerplate. Simple but a lot to demonstrate the problem in very detail.
The schema of the Track (I'll omit other types to reduce the code boilerplate):
type Track {
id: ID!
title: String!
author: Author!
thumbnail: String
length: Int
modulesCount: Int
description: String
numberOfViews: Int
modules: [Module!]!
}
The readQuery example with the all the Track fields:
const { track } = client.readQuery({
query: gql`
query getTrack($trackId: ID!) {
track(id: $trackId) {
id
title
author {
id
name
photo
}
thumbnail
length
modulesCount
numberOfViews
modules {
id
title
length
}
description
}
}
`,
variables: {
trackId: 'c_1',
},
});
The result is:
{
"__typename": "Track",
"id": "c_1",
"title": "FAMOUS CATSTRONAUTS",
"author": {
"__typename": "Author",
"id": "cat-2",
"name": "Grumpy Cat",
"photo": "https://images.unsplash.com/photo-1593627010886-d34828365da7?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExNzA0OH0"
},
"thumbnail": "https://res.cloudinary.com/dety84pbu/image/upload/v1598474100/famous_cats_epuqcr.jpg",
"length": 1916,
"modulesCount": 5,
"numberOfViews": 26,
"modules": [
{
"__typename": "Module",
"id": "l_10",
"title": "Neil Armstrong",
"length": 321
},
{
"__typename": "Module",
"id": "l_11",
"title": "Yuri Gagarin",
"length": 470
},
{
"__typename": "Module",
"id": "l_12",
"title": "Buzz Aldrin",
"length": 545
},
{
"__typename": "Module",
"id": "l_13",
"title": "John Glenn",
"length": 357
},
{
"__typename": "Module",
"id": "l_14",
"title": "Chris Hadfield",
"length": 223
}
],
"description": "Be inspired by famous catstronauts who have made their names legend from across the galaxies. Special guest appearance included, so hold on to your boots!"
}
Now the readFragment example (all fields):
const track = client.readFragment({
id: 'Track:c_1',
fragment: gql`
fragment MyTrack on Track {
id
title
author {
id
name
photo
}
thumbnail
length
modulesCount
numberOfViews
modules {
id
title
length
}
description
}
`
});
The result is the same as in the case of the readyQuery.
Now the example with the partial fields.
For the readQuery:
const { track } = client.readQuery({
query: gql`
query getTrack($trackId: ID!) {
track(id: $trackId) {
id
title
}
}
`,
variables: { // Provide any required variables here. Variables of mismatched types will return `null`.
trackId: 'c_1',
},
});
The result will be:
{
"__typename": "Track",
"id": "c_1",
"title": "FAMOUS CATSTRONAUTS"
}
The readFragment (partial fields)
const track = client.readFragment({
id: 'Track:c_1',
fragment: gql`
fragment MyTrack on Track {
id
title
}
`
});
The result will be the same as readyQuery!
My question: When should I use the readQuery and when the readFragment? It looks like they provide the same result.
The same for writeQuery and the writeFragment. They do the same at the first look.
writeQuery partial update code example:
client.writeQuery({
query: gql`
query WriteTrack($trackId: ID!) {
track(id: $trackId) {
id
title
},
}`,
data: { // Contains the data to write
track: {
__typename: 'Track',
id: 'c_1',
title: 'Buy grapes 🍇',
},
},
variables: {
id: 'c_1'
}
})
writeFragment partial update code example:
client.writeFragment({
id: 'Track:c_1',
fragment: gql`
fragment MyTrack on Track {
id
title
}
`,
data: {
__typename: 'Track',
id: 'c_1',
title: 'Buy grapes 🍇',
}
})
The result is the same. Both update the title. So what is the difference? When should I use the writeQuery and when the writeFragment?
Thanks for any help and your patience and time!

How to create a List Render JSON from a Dynamic List for an API response in Vue?

I am a beginner in at Vue.js version 2.6.11.
I have a form where a person can add a list of toys. So the list is dynamic. How do we add this dynamic list into a JSON data structure in a POST request?
I cannot change the API.
For example the first list to send to a POST request might be
"toyCollection":
[
{
"toyName": "yo-yo",
"toyDescription": "ball on a string",
"toyAge": 15,
"company": {
"companyName": "yo yo company"
"companyYear": "1999"
}
}
]
The second time someone creates a list of toys in this dynamic list might be
"toyCollection":
[
{
"toyName": "yo-yo",
"toyDescription": "ball on a string",
"toyAge": 15,
"company": {
"companyName": "yo yo company"
"companyYear": "1999"
}
},
{
"toyName": "barbie",
"toyDescription": "dolls in a house",
"toyAge": 21,
"company": {
"companyName": "mattel"
"companyYear": "1959"
}
},
{
"toyName": "transformers",
"toyDescription": "robots in disguise",
"toyAge": 20,
"company": {
"companyName": "Hasbro"
"companyYear": "1984"
}
}
]
How do we write this in Vue so that this is dynamic?
methods: {
const postRequest = {
toyCollection: [ //if 1 toy in list
{
toyName: "yo-yo", // this.form.toyName <---- would read the data
toyDescription: "ball on a string", //hardcoded here for simplicity for example
toyAge: 15,
company: {
companyName: "yo yo company"
similarToysFromCompany: "1999"
}
}
]
}
}
If there are three toys in the collection
methods: {
const postRequest = {
toyCollection: [ //if 3 toys in list
{
toyName: "yo-yo",
toyDescription: "ball on a string",
toyAge: 15,
company: {
companyName: "yo yo company"
similarToysFromCompany: "1999"
}
},
{
toyName: "barbie",
toyDescription: "dolls in a house",
toyAge: 21,
company: {
companyName: "mattel"
companyYear: "1959"
}
},
{
toyName: "transformers",
toyDescription: "robots in disguise",
toyAge: 20,
company: {
companyName: "Hasbro"
companyYear: "1984"
}
}
]
}
}
The list can be any size, depending on how many toys a person adds to this list.
How do we make this dynamic based on the list?
Then I would call my API with this object
this.methodCallToAPI(postRequest);
Thanks for any help!
==============
EDIT
I have a template to input fields
<form>
<!-- Name -->
<input
v-model="form.toyName"
id="toy-name"
class="input"
type="text"
/>
</div>
</form>
Then in the Script, it watches or updates the data fields based on what the user types into the input text fields.
export default {
name: "CreateToyCollection",
data () {
return {
form: {
toyName: "",
toyDescription: "",
toyAge: "",
company: {
companyName: "",
similarToysFromCompany: ""
}
}
}
},
watch: {
this.form.toyName = "";
this.form.toyDescription = "";
this.form.toyAge = "";
// etc for Company
}
}
I'm working on the list part, but this is how I want to pass in the dynamic data
In the data add a new array toyCollection :
data () {
return {
toyCollection: [],
form: {
toyName: "",
...
},
...
Every time form is submitted, push the submitted data to it like this.toyCollection.push(data)
Later in your post request you can send this.toyCollection as the payload.

Why v-for & axios not loading items one by one?

I am creating a product web-app by using vue-2.6.11, axios-0.21.1, vuetify-2.4.3
I am fetching categories from local array then I am passing fetchUrl as Props it into Row component by using v-for . Then in Row component i am fetching the fetchUrl by using axios after getting API response I'm simply mounting it. It working fine but the problem is categories object means Row component loads in random order cause the Row component mounted as it got axios response from API.
So I want Next row await till upper fully-mounted or any thing else to make it orderly loaded.
My Components :
Home.vue -
<template>
<div>
<div v-for="(categories,index) in categories" :key="`${index}`">
<ItemsCarousel
:title="categories.title"
:fetch-url="categories.fetchUrl"
/>
</div>
</div>
</template>
<script>
import categoriesList from '#/local-database/Categories.json';
import ItemsCarousel from '#/components/carousel/ItemsCarousel';
export default {
name: 'Home',
components: {
ItemsCarousel
},
data: () => ({
categories: categoriesList.filter( categories => (catalogue.for==true || categories.for=="home"))
})
}
</script>
ItemsCarousel.vue -
<template>
<div class="items-carousel">
<v-lazy v-model="isActive" :options="{threshold: 0.5}">
<h1>{{title}}</h1>
<div class="items-carousel" v-for="product in products" :key="product.id">
<Card v-bind="{...product}">/>
</div>
</v-lazy>
</div>
</template>
<script>
import ProductManger from '#/mixins/ProductManger';
import Card from '#/components/Card';
export default {
name: 'ItemsCarousel',
mixins: [ProductManger], // Axios Setup
components: {
Card
},
props: ['title','params'],
data: () => ({
isActive: false,
cards: []
}),
methods: {
async loadCard() {
this.contentMangerCore(this.params) // Function code inside mixins
.then(res => {
this.cards = res.data;
})
}
},
mounted() {
this.loadCard();
}
};
</script>
DataSample :-
categoriesList.json-
[{
"id": 1,
"name": "Adventure",
"params": {
"categories": "Adventure",
"sort": "ASC"
}
}, {
"id": 2,
"name": "Art",
"params": {
"categories": "Art",
"sort": "DESC"
}
}, {
"id": 3,
"name": "Beauty",
"params": {
"categories": "Art",
"sort": "DESC"
}
}, {
"id": 4,
"name": "Business",
"params": {
"categories": "Art",
"sort": "DESC"
}
}, {
"id": 5,
"name": "Craft",
"params": {
"categories": "Art",
"sort": "DESC"
}
},...]
products.json-
[{
"name": "AdventureIRC",
"img": "..."
},
{
"name": "Adventie",
"img": "..."
},...]
I Hope you guys will help me to resolve this...
Thank You :smile:
You could make a computed method that determines how many categories to actually display at any given time, incremented by successful axios requests.
get categoriesForDisplay() {
return this.categories.slice(0, this.successfulCarouselFetches + 1)
}
Then define successfulCarouselFetches :
data() {
return {
//
successfulCarouselFetches : 0
}
}
listen for successful axios requests in your Item-Carousel component:
<ItemsCarousel
:title="categories.title"
:fetch-url="categories.fetchUrl"
#success="successfulCarouselFetches = successfulCarouselFetches + 1"
/>
Now broadcast the success whenever your xhr is done working:
methods: {
async loadCard() {
this.contentMangerCore(this.params) // Function code inside mixins
.then(res => {
this.cards = res.data;
this.$emit('success');
})
}
},
When the page loads you'll have a single Item-Carousel component on the page which will perform the first XHR request. When the component $emit's the event, the parent component containing the v-for will increment the successfulCarouselFetches which will allow the getter categoriesForDisplay to add another Item-Carousel within the v-for.
This essentially performs what you're asking for, I believe.

When i modify a variable that depends of my parent state i dont want that modify the initial state

I'm trying to set a filter, so, what i'm doing is first creating a new variable called filteredDataParentSate which is the total state of my principal class, inside i have the data(array of objects) that i want to filter, i use .filter function to generate the filtered array, i set this filtered data on my previos variable filteredDataParentSate. i pass the total filteredDataParentSate to my component which show the data.
The filter works fine when i write the input, the problem is that i don't know why the parentState also modify, so when i delete the input the data didn't return to the original state.
render() {
let filteredDataParentSate = this.props.parentState
let filterdData = filteredDataParentSate.data.filter(
(dat) =>{
return dat.nombre_completo.toLowerCase().indexOf(filteredDataParentSate.search.toLowerCase()) !== -1;
}
)
console.log(this.props.parentState.data)
filteredDataParentSate.data = filterdData
console.log(this.props.parentState.data)//this have to return the same that the previous console.log, but this return the filtered data
Here i send the data to the component that show it
<TableNotTableRender
parentState={filteredDataParentSate}
methods={{
handleshow: this.handleshow,
addRecaudo: this.addRecaudo,
deletetransaction: this.deletetransaction,
cancelTransaction: this.props.methods.cancelTransaction,
prealistadoButton: this.props.methods.prealistadoButton,
showProducts: this.props.methods.showProducts,
isDelivered: this.props.methods.isDelivered,
sort: this.props.methods.sort,
updateSearch: this.props.methods.updateSearch
}}
>
and in my parentstate this is my state:
class ListarClientes extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
globalTitle: "Clientes",
addedProductos: [],
id_usuario: "",
productsPrice: "",
totalPrice: "",
rebatePrice: "",
shippingPrice: "",
data: [],//
indexSort: "",
orderSort: "",
search: "",
the data in my state fills with a get call, this is the data to filter, normally is something like this:
"data": [
{
"id_usuario": "18",
"nombre_completo": "Nuevo cliente",
"tipo_identificacion": "CC",
"identificacion": "103855555",
"celular": "20202020",
"fk_ciudad": "1",
"fk_departamento": "52",
"correo": "nuevo.cliente#nuevo.com",
"direccion": "calle 82a # 70-78",
"estrato": "3",
"canal_adquisicion": "Referida",
"fecha_nacimiento": "1994-12-10",
"fk_id_usuario": "15",
"fk_id_campana": null,
"edad": 32,
"createdAt": "2020-08-26T02:33:46.223Z",
"updatedAt": "2020-08-26T21:47:43.196Z",
},
{
"id_usuario": "15",
"nombre_completo": "Otro Cliente",
"tipo_identificacion": "CC",
"identificacion": "1038444444",
"celular": "3190000000",
"fk_ciudad": "1",
"fk_departamento": "1",
"correo": "otro#otro.com",
"direccion": "calle 82a",
"estrato": "3",
"canal_adquisicion": "Referida",
"fecha_nacimiento": "1996-01-16",
"fk_id_usuario": "13",
"fk_id_campana": null,
"edad": 24,
"createdAt": "2020-08-22T02:31:52.254Z",
"updatedAt": "2020-08-28T20:52:03.010Z",
},
]
this is my method that update the search input
updateSearch = (event) => {
this.setState({ search: event.target.value })
}

How get extra information from json?

I use can.Component to dispay JSON on the page.
can.Component.extend({
tag: "some-app",
scope: {
items: new Items.List({}),
displayedItems: function () {
...
return items;
}
},
helpers: {
...
},
events: {
"{Items} created": function (Items, ev, newItem) {
...
}
}
})
How can I get "meta" section of received JSON (below) to the scope or helpers?
{
"data": [
{
"description": "Some text",
"id": 1,
"measurement": "pcs",
"name": "Name of item",
"resource_uri": "/api/v1/item/1/"
},
{....}, {....}
}
],
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 3
}
}
I can get it in console with Items.findAll().then(function(info){console.log(info.attr('meta'))}) , but I'm noob in (can.)js and can't understand how to get it in the place I need.
Instead of this:
scope: {
items: new Items.List({})
}
make the request:
scope: {
items: Items.findAll()
}
There are other ways to do this as well, in the template(not advised), or creating the request in another controller or component and passing in to the instantiation of the component.
If you want more specifics, you would nee to update your question with more details on your model.

Categories