Vue js - reference variable in object - javascript

I am new to vue and can't find a solution to this -
I have a JSON object here, and I am trying to dynamically fetch the "info" of a user based on their "userRegion".
{
"userData": {
"kr": {
"info": {
"name": "testing-123",
}
},
"any": null,
"us": null,
"eu": {
"info": {
"name": "testing-456",
}
},
},
"userRegion": "eu"
}
I then have this object in vue and I want to dynamically change region and pull the data from the object based on this region value in the "user" object below.
user:{
region: this.userData.userRegion,
name: this.userData[this.user.region].info.name
},
For example, I have tried using something like this
this.userData.userData[this.user.region]
but I get an error:
TypeError: Cannot read property 'region' of undefined"
the variable I am using "userData" is passed down from the parent like so:
<infoWindow :userData='userData'></infoWindow>
and is set as a prop:
props: {
userData: app.userData,
},
any help would be aprpeciated, thanks

I don’t really understand where you are setting this user, whether its part of an initialized data object, or a computed property. However, there is a temporal issue there:
user: {
region: this.userData.userRegion,
name: this.userData[this.user.region].info.name
},
In order to set up user.name, user.region needs to be already there. But since you are creating the user object at once, this does not work. So you either have to split that up, or repeat the logic for the user region again:
user: {
region: this.userData.userRegion,
name: this.userData[this.userData.userRegion].info.name
},

Related

Unflattening line items in inputData when rendered by function

I have dynamic children input fields that need to be rendered in a function, but when they are, then they are not included in inputData properly/not under the parent input field's key. When the children are included directly in the inputFields, it works as expected, but I can't use a function within the children array with Zapier.
Here is the inputData currently, when the line items are rendered in a function, the LI_ denotes that it is a child input key -
"inputData": {
"supplier": "1",
"LI_budget": 1,
"LI_tax": 1,
"company": "1",
"currency": "1",
"LI_price": "1",
"LI_description": "1"
}
I'm expecting ("parent" is the inputField parent key here):
"inputData": {
"supplier": "1",
"parent": [{
"LI_budget": 1,
"LI_tax": 1,
"LI_price": "1",
"LI_description": "1"
}],
"company": "1",
"currency": "1",
}
This is the function I'm using to pull in the parent and children input fields:
const getLineItems = async (z, bundle) => {
let lineItem = {
key: 'parent',
children: [{
key: 'LI_description',
label: 'Description',
required: true
},
{
key: 'LI_budget',
required: true,
label: 'Budget',
dynamic: 'budget.id'
},
{
key: 'LI_price',
required: true,
type: 'number',
label: 'Unit price',
helpText: 'Example: 50.25'
},
{
key: 'LI_tax',
required: true,
label: 'Tax Rate',
dynamic: 'tax_rate.id'
},
]
}
return [lineItem];
};
There are dynamic fields generated in the getLineItems function that I took out to simplify. TIA
Caleb here from Zapier Platform Support. This is a tough one! We have a pretty long-standing issue report on our platform for supporting custom fields with parent keys (it boils down to a chicken vs the egg problem that really makes my head spin when I read the discussion on the issue). Your inputFields function is spot-on, it's just a matter of properly storing it in the bundle on our part.
I think we could cobble together a workaround to unflatten it. Before I do that though, could you give this a test in the editor and submit actual line items from a previous step to this step? I'm not sure what the inputData looks like (e.g. if multiple items are split like 1,2,3 or in some other fashion). If you want to iterate on this, it might be better to switch over to our public developer Slack (http://zpr.io/ttvdr); then we can post the results here for the next person to run into this. 😁

Unable to send Firebase QueryDocumentSnapshot over API Call

I'm currently making my first network call in a paginated series of calls on the server side. Prior to doing this I was making all of the calls client side and stored the last document in the collection call as an offset.
The offset was then sent as a .startAfter call for the same collection. The offset document looked like this:
exists: (...)
id: (...)
metadata: (...)
ref: (...)
_document: Document {key: DocumentKey, version: SnapshotVersion, data: ObjectValue, proto: {…}, hasLocalMutations: false, …}
_firestore: Firestore {_queue: AsyncQueue, INTERNAL: {…}, _config: FirestoreConfig, _databaseId: DatabaseId, _dataConverter: UserDataConverter, …}
_fromCache: false
_hasPendingWrites: false
_key: DocumentKey {path: ResourcePath}
__proto__: DocumentSnapshot
When I make the call on the server I'm currently able to see the document looks the same, but when I send it over the network it seems to be stripped or at least looks very different by the time it's sent over JSON and parsed back.
Sent like this:
res.json(offset)
then parsed like this:
feedData = await dataWithOffset.json();
After the parsing it looks like this:
{ _ref:
{ _firestore:
{ _settings: [Object],
_settingsFrozen: true,
_serializer: [Object],
_projectId: '***-prod',
_lastSuccessfulRequest: 1566308918946,
_preferTransactions: false,
_clientPool: [Object] },
_path:
{ segments: [Array],
projectId: '***-prod',
databaseId: '(default)' } },
_fieldsProto:
{ lastModified: { timestampValue: [Object], valueType: 'timestampValue' },
...,
_serializer: { timestampsInSnapshots: true },
_readTime: { _seconds: 1566308918, _nanoseconds: 909566000 },
_createTime: { _seconds: 1565994031, _nanoseconds: 304997000 },
_updateTime: { _seconds: 1565994031, _nanoseconds: 304997000 } }
Any idea why it is losing its shape and what I can do to fix it so it returns to working as a proper offset? Should I not be converting to JSON and back, as that may strip some important things?
Solution (tested)
So I went ahead and made a sandbox to test the implementation, and like I mentioned in the comments .startAfter expects a DocumentSnapshot not a DocumentReference
Given that I created a collection named cars with 4 records like this:
[
{
"name": "car 1",
"hp": 5
},
{
"name": "car 2",
"hp": 10
},
{
"name": "car 2.5",
"hp": 10
},
{
"name": "car 3",
"hp": 15
}
]
Then I configured an express endpoint:
router.get('/cars/:lastDocId', (req, res) => {
const query = db.collection('cars')
.orderBy('hp')
.limit(2);
const handleQueryRes = (snap) => {
return res.send({
docs: snap.docs.map(doc => doc.data()),
last: snap.docs.length > 0 ? snap.docs[snap.docs.length - 1].id : null
});
}
if(req.params.lastDocId != -1) {
// this makes an "auxiliar" read from the DB to transform the given ID in a DocumentSnapshot needed for startAfter
return db.collection('cars').doc(req.params.lastDocId).get().then(snap => {
return query.startAfter(snap).get();
}).then(handleQueryRes).catch(console.log);
} else {
return query.get().then(handleQueryRes).catch(console.log);
}
});
The path parameter lastDocId is either -1 for first page or the last document fetched in the previous page
When I make a GET request to /cars/-1 it returns this:
{
"docs": [
{
"hp": 5,
"name": "car 1"
},
{
"name": "car 2",
"hp": 10
}
],
"last": "9sRdLOvV8REwEpHDjEw7"
}
Now if I grab the last prop in the response and use it in my next GET like so /cars/9sRdLOvV8REwEpHDjEw7 I get my next 2 cars:
{
"docs": [
{
"name": "car 2.5",
"hp": 10
},
{
"name": "car 3",
"hp": 15
}
],
"last": "tZPF7Wav7jZuchoCp6zM"
}
Even though I only have 4 records and the second request should be the last the function does not know the length of the collection so it returns another last ID
If you make the last request /cars/tZPF7Wav7jZuchoCp6zM it returns:
{
"docs": [],
"last": null
}
Thus giving indication that is the last page.
I'm not too fond of having to read the document again to transform it into a DocumentSnapshot but I guess that's a firebase limitation
Hope it helped
Answer with steps
When converting to JSON and back you lose the DocumentReference prototype
The solution to pass that type of data through network requests is:
Client sends a plain-text ref to your endpoint ( or doesn't for first page)
Have the server side code re-create the DocumentReference with the received ref
Use the re-created DocumentReference to paginate query
Return from server the requested page's documents alongside with a plain-text refto get the next page
Initial answer (obsolete) but for future reference
You need to send offset.data() instead of sending offset alltogether
One is the document's data (probably what you're after) the other is a DocumentReference which has methods that cannot be represented in JSON.
If you need anything else from the document (like it's id or reference) you're better off building a new object:
res.json({
data: offset.data(),
ref: offset.ref,
id: offset.id
});

Sequelize is returning null values when used with include

When querying a model with include, incase of no rows available, it is returning data with null values.
I know this problem has been posted many times before, but i have not found any conclusions till now.
Model.findOne({
where: { id: 1 },
include: [{model: Model1}]
})
Result i am getting is like
{
"id": null,
"name": null,
"age": null,
"model1": []
}
If i use raw: true, it is printing like
{
"id": null,
"name": null,
"age": null,
"model1.model1n": 0
}
One cause of this is if you exclude id from attributes. If you're using scopes or attributes in your includes or through tables, make sure you're returning the id primary key.
Another cause of this is if you return null in a custom get() getter function on the column.

Add fields in DevExpress Pivot using AngularJS

I'm looking at this template to build a web application: https://js.devexpress.com/Demos/WidgetsGallery/Demo/PivotGrid/FieldChooser/AngularJS/Light/
In the example there are static data. I have to retrieve them from the server. So, I wrote this:
$scope.testData = [];
$scope.pivotGridDataSource = new DevExpress.data.PivotGridDataSource({
fields: [{
caption: "Nome",
dataField: "fullName",
area: "row"
}, {
caption: "Country",
dataField: "country",
area: "column"
}, {
caption: "Count",
dataField: "countOne",
dataType: "number",
summaryType: "sum",
area: "data"
}],
store: $scope.testData
});
$scope.pivotGridOptions = {
allowSortingBySummary: true,
allowSorting: true,
allowFiltering: true,
showBorders: true,
dataSource: $scope.pivotGridDataSource,
fieldChooser: {
enabled: false
}
},
$scope.fieldChooserOptions = {
dataSource: $scope.pivotGridDataSource,
texts: {
allFields: "All",
columnFields: "Columns",
dataFields: "Data",
rowFields: "Rows",
filterFields: "Filter"
},
width: 400,
height: 400,
bindingOptions: {
layout: "layout"
}
};
// Now I call the server to retrieve data
$scope.getTestData = () => {
$scope.testData.length = 0;
result.forEach(e => {
$scope.testData.push(e);
);
$scope.pivotGridDataSource.reload();
}
$scope.getTestData();
The problem is that when the data are loaded, in the Fields below it shows just the fields written at the beginning (so the name, the count and the country). But I saw in the demo that it should be display ALL parameters of the object.
For example, if the object is so structured:
{ "name": "Test1", "country": "Germany", "creationDate": "xxx", "surname": "yyy" }
So, I expect that in the fields there should be ALL parameters, so name, country, creationDate, surname. So, I did this at the beginning:
I changed $scope.testData = [] into:
$scope.testData = [{ "name": "", "country": "", "creationDate": "", "surname": "" }]
so the component will preparare all fields. And this works. But what if the server gives me back an Object that has another parameters? How can I display them?
I tried so after the calling and before the reload():
let fields = $scope.pivotGridDataSource.fields();
let newField = {
llowExpandAll: false,
allowFiltering: true,
allowSorting: true,
allowSortingBySummary: true,
caption: "This is a new field",
dataField: "newField",
dataType: "string",
displayFolder: "",
index: fields.length
}
$scope.pivotGridDataSource.fields().push(newField);
$scope.pivotGridDataSource.reload();
But it doesn't work yet. Worse, it does not even initialize the Pivot.
The fieldChooser uses the store fields, in this case $scope.testData fields, in your code I see your store is first declared (as null or with some format as you described) and then you have a function to fill it.
I don't know how your code looks and why you create your store that way, but that is basically your problem (the flow).
In the sample code the flow is:
Store with data (static in this case)
PivotGridDataSource
FieldChooser
In your code the flow is:
Store (empty)
PivotGridDataSource
FieldChooser
Store (fill) --> at this point your FieldChooser has been initialized with the fields of the empty version of your store so not much to do (in Jquery you could re-create your object, you dan do it using Jquery within AngularJs see a simple code sample here and below)
$('#chartContainer').dxChart('instance').dispose();
$('#chartContainer').dxPieChart({
...
});
To avoid all of this you can just use the DevExpress.data.CustomStore and your flow will be basically identical to the demo.

how to properly specify nested OData $expand to Angular $odataresource directive?

In my Angular app I'm using $odataresource directive to consume OData v4 feed in the following way:
http://10.0.0.4:8080/InformationProduct?$expand=DataEntities($expand=DataSources)
This query runs fine in Fiddler, Postman, as well as any modern browser:
{
#odata.context: "http://10.0.0.4:8080/$metadata#InformationProduct",
value: [{
ID: 1,
Name: "ODM Dashboard",
Description: "ODM Dashboard",
Governance_ID: 1,
PerformanceMetric_ID: 1,
DataEntities: [{
ID: 1,
Name: "Data Entity 1",
Description: "Data Entity 1",
InformationProduct_ID: 1,
BiMeasure_ID: null,
BiFact_ID: null,
BiDimension_ID: 1,
DataSources: [{
ID: 40,
Category: "Service Performance",
SourceSystemName: "Account Improvement Plan",
SourceSystemOwner: null,
SourceSystemLocation: null,
SourceSystemTeam: null,
SourceSystemNetworkSegment: null,
SourceSystemOsType: null,
SourceDatabaseName: null,
SourceDatabaseType: null,
SourceDatabaseVersion: null,
BiFact_ID: null
}]
}]
}]
}
I'm trying to implement the same query within my Angular controller like this:
function getData(){
$odataresource("http://windows-10:8080/InformationProduct")
.odata()
.expand('SourceTools')
.expand('DataEntities','DataSources')
{}
}
I'm getting this error:
GET http://windows-10:8080/InformationProduct?$expand=SourceTools,DataEntities/DataSources 400 (Bad Request)
It is clear, that $odataresource does not translate .expand('DataEntities','DataSources')
into $expand=DataEntities($expand=DataSources) as expected
What is the proper way to have $odataresource directive produce such nested $expand?
The docs state that you need to use the isodatav4 property to let it know that you are using a v4 endpoint:
To enable this behavior set the isodatav4 property to true when
invoking the $odataresource method:
User = $odataresource('/user', {}, {}, {
odatakey: 'id',
isodatav4: true
});
Then use the expand method like this:
var result = User.odata().expand("roles", "role").query();
// /user?$expand=roles($expand=role)
For you, this means that you have the right expand call already, you just need to add the isodatav4 flag to $odataresource("http://windows-10:8080/InformationProduct") to make $odataresource("http://windows-10:8080/InformationProduct", {}, {}, { isodatav4: true })

Categories

Resources