Breeze and Knockout not binding correctly - javascript

I was trying a sample using breeze and knockout
manager.executeQuery(query).then(function(result){
console.log(result);
ko.applyBindings(result);
}).fail(function(e) {
console.log(e);
alert(e);
});
While printing in the console. I'm getting two objects in the path data.XHR.result.responseJSON and two objects in data.results
But in the view created as a result of knockout binding I'm getting the second set of value populated two times. (I have two set of values in the db)
NOTE: This code is working if I havent defined any metadata. Issue is in the scenario where I use metadata
metadata
var sample=sample||{};sample.metadata=
{
"dataServices":[
{
"serviceName":"/sample",
"hasServerMetadata":true,
"jsonResultsAdapter":"webApi_default",
"useJsonp":false
}
],
"structuralTypes":[
{
"shortName":"Employee",
"autoGeneratedKeyType":"None",
"defaultResourceName":"Employee",
"dataProperties":[
{
"name":"id",
"dataType":"MongoObjectId",
"isNullable":false,
"defaultValue":"",
"isPartOfKey":true,
"validators":[
{
"name":"required"
}
]
},
{
"name":"name",
"dataType":"String",
"maxLength":100,
"validators":[
{
"maxLength":100,
"name":"maxLength"
}
]
},
{
"name":"age",
"dataType":"String",
"maxLength":100,
"validators":[
{
"maxLength":100,
"name":"maxLength"
}
]
}
]
}
],
"resourceEntityTypeMap":{
"Employee":"Employee"
}
};

Make sure that you have a primary key that is defined in your model and coming across the wire. If you leave those values as null they will overwrite each other when breeze adds them to the cache and sees the keys are the same.

Related

Access array inside JSON object using Axios Vue JS

I need to access arrays inside JSON object and save into different arrays. I tried few ways but no luck.
I could get all other values without any problem but when it comes to arrays I couldn't retrieve those.
I feel the way I try to access arrays inside JSON object might be wrong and but I couldn't figure it out
Here is JSON object
{
"packId":51,
"shortCode":"TTY",
"packDescription":"TTY Des",
"startDate":"2020-09-01",
"endDate":"2020-09-08",
"validityValue":30,
"validityType":"Hours",
"expiryAction":true,
"expirySMS":64,
"activationSMS":64,
"deactivationSMS":64,
"subscriptionSMS":0,
"deactivationAction":true,
"deactivationShortCode":"DEACT TTY",
"deprovisionOnExpiry":true,
"deleteByPackType":true,
"packType":{
"packTypeId":2,
"name":"Facebook"
},
"timeBands":[
{
"timeBandId":1,
"start":"8:00",
"end":"23:00",
"timeBand":"8:00-23:00"
},
{
"timeBandId":2,
"start":"8:00",
"end":"20:00",
"timeBand":"8:00-20:00"
}
],
"activationTypes":[
{
"activationTypeId":1,
"name":"SMS"
},
{
"activationTypeId":2,
"name":"Web"
}
],
"channels":[
{
"channelId":1,
"name":"hShenid"
},
{
"channelId":2,
"name":"Genesis"
}
],
"users":[
]
}
Axios Call
getPackById(id)
{
return axios.get(`${API_URL}/pack/get/${id}`);
}
refreshPack()
{
PackComposeDataService.getPackById(this.id).then((res)=>
{
//I can access these values without any problem
this.deleteByPackType= res.data.deleteByPackType,
this.packTypeValues=res.data.packType,
this.shortCode= res.data.shortCode,
this.packDescription= res.data.packDescription,
this.startDate= res.data.startDate,
this.endDate= res.data.endDate,
this.subscriptionSMS= res.data.subsNotificationValues["id"],
this.validityValue= res.data.validityValue,
this.validityType= res.data.validityType,
this.actionOnExpiry= res.data.expiryAction,
this.expirySMS= res.data.expiryNotificationValues,
this.activationSMS= res.data.activationNotificationValues,
this.deactivationAction= res.data.deactivationAction,
this.deactivationShortCode= res.data.deactivationShortCode,
this.deactivationSMS= res.data.deactivationNotificationValues,
this.deprovisionOnExpiry= res.data.deprovisionOnExpiry,
//I need to get these arrays
this.timeBandValues= res.data.timeBands,
this.activationTypes= res.data.activationTypes,
this.channels= res.data.channels,
this.users= res.data.users
});
I understand you want to take only the timeBand string of each of the arrays (or the activationType, eventually).
If that's the case, you may want to map to convert each object in the array to a simple string:
// ...
this.timeBandValues = res.data.timeBands.map(o => o.timeBand) // you're going to get ["8:00-23:00", "8:00-20:00"]
// ...

how to loop through array of json objects in angularjs

I have a auto search module with below json structure. I need to loop through aray of json objects and use key and value as per requirements.
I have tried below code. But with provided json object, I am able to retrieve key, but not value.
lets say, for firt, Json object, I need to retrieve 'Product Apple'., but I`m getting only link.
I tried response.data[key][0] ,but getting full json object. May I Know where I have done wrong.
I have updated plunker below
[{
"/folder1/folder2/folder3/product-1": "Product Apple"
},
{
"/folder1/folder2/folder3/product-2": "Product samsung"
},
{
"/folder1/folder2/folder3/product-3": "Product lenovo"
},
{
"/folder1/folder2/folder3/product-4": "Product Asus"
},
{
"/folder1/folder2/folder3/product-5": "Product Acer"
},
{
"/folder1/folder2/folder3/product-6": "Product Vivo"
},
{
"/folder1/folder2/folder3/product-7": "Product Oppo"
}
]
code here
Since this is marked as duplicate post., I have gone through the provided solution and found that the duplicate post has solution via javascript. But I`m looking to iterate through angularjs 'ng-repeat'.
Please find plunker below for solution I have got
[code here][1]
code here
You probably want to assign that structure to a variable, and then run an *ngFor on it, like this:
// in the component file
let results = [
{
"/folder1/folder2/folder3/product-1":"Product Apple"
},
{
"/folder1/folder2/folder3/product-2":"Product samsung"
},
{
"/folder1/folder2/folder3/product-3":"Product lenovo"
},
{
"/folder1/folder2/folder3/product-4":"Product Asus"
},
{
"/folder1/folder2/folder3/product-5":"Product Acer"
},
{
"/folder1/folder2/folder3/product-6":"Product Vivo"
},
{
"/folder1/folder2/folder3/product-7":"Product Oppo"
}
]
// in the view
<ng-container *ngFor="let result of results">
view logic goes here
</ng-container>

Only download Firebase snapshots that have child key

My data structure looks like this (removed unnecessary parts):
{
"threads" : {
"PUSHID" : {
"info" : {
"members" : {
"uid" : true,
"uid2" : true
}
}
}
}
}
I'm trying to write some javascript to pull snapshots of threads a user is in, but I can't figure out a way for it to work without pulling snapshots of each thread. This is my code now that pulls each thread snapshot.
firebase.database().ref('threads').on('child_added', function(snapshot) {
if (snapshot.hasChild('info/members/' + userUid)) {
// Display thread info
}
});
I tried to make a query with .orderByChild('info/members/' + userUid) and removing null snapshots, but I would have to add a .indexOn for each userUid which is obviously not practical.
Your current structure makes it easy/efficient to look up the users for a thread. But your use case is to look up the threads for a user. You'll need to augment your data model to allow the use-case:
{
"user_threads" : {
"uid": {
"PUSHID": true,
"PUSHID2": true
},
"uid2": {
"PUSHID": true,
"PUSHID3": true
}
}
}
And then read it with:
firebase.database().ref('user_threads/'+userUid).on('child_added', function(snapshot) {
...
});
Modifying/expanding your data model to match the use-cases of your app is quite common when using NoSQL databases.

How can I build a compound query with SearchBox in searchkit?

I'm using searchkit to try to build a basic text search. I think the query I want to build is fairly simple. It needs to be structured like this:
{
"query":{
"bool":{
"must":[
{
"multi_match":{
"query":"test search",
"type":"phrase_prefix",
"fields":[
"field_1^5",
"field_2^4",
"field_3"
]
}
},
{
"term":
{
"field_id": "3"
}
}
],
"must_not":[
{
"term":
{
"status": "archived"
}
}
]
}
},
"size":6,
"highlight":{
"fields":{
"field_1":{},
"field_2":{},
"field_3":{}
}
}
}
I've tried using the prefixQueryFields attribute, which gave me something fairly close to what I wanted except it was using a BoolShould rather than a BoolMust, plus it was always including the default SimpleQueryString query. It looked something like this:
const prefixQueryFields = [
'field_1^5',
'field_2^4',
'field_3',
];
...
<SearchBox
searchOnChange={true}
prefixQueryFields={prefixQueryFields}
/>
I couldn't figure out the issues there easily and decided to go with the queryBuilder attribute in SearchBox. This is what I came up with:
_queryBuilder(queryString) {
const prefixQueryFields = [
'field_1^5',
'field_2^4',
'field_3',
];
return new ImmutableQuery()
.addQuery(BoolMust([
MultiMatchQuery(queryString, {
type: 'phase_prefix',
fields: prefixQueryFields,
})
]))
.addQuery(BoolMustNot([
TermQuery('status', 'archived'),
]));
}
...
<SearchBox
searchOnChange={true}
queryBuilder={this.queryBuilder}
/>
This query came out even more messed up, and I have no idea what to try next after checking the documentation and a cursory look at the source code.
(For the sake of brevity, I will not bother including the incorrect queries these two attempts created unless someone thinks that info will be useful.)
Figured it out. Using the QueryDSL structures wasn't working out very well, but apparently you can create the query with pure JSON, which worked great. Basically updated my query builder to return as so:
return {
bool: {
must: [
{
multi_match:{
query: queryString,
type: 'phrase_prefix',
fields: prefixQueryFields,
}
}
],
must_not: [
{
term: {
status: 'archived',
}
}
]
}
};

Swapping data in Angular UI-Grid, new columns not visible when changing dataset externally

I've got a query tool I've been working on, which has an angular form that is filled out, and then when it's submitted it uses AJAX which returns JSON, which is then rendered into ui-grid, that JSON response looks like
{
"success": true,
"message": "",
"columns": ["first_name", "last_name", "company", "employed"]
"results": [
{first_name: "John", last_name: "Smith", company: "Abc Inc", employed: true},
{first_name: "Johnny", last_name: "Rocket", company: "Abc Inc", employed: true}]
}
I'm working on both the PHP and angular so I have full control over this JSON response if need be. I'm running into an issue when my JSON response from a first AJAX call is rendered, and then I run another, seperate AJAX call on the same page and get a new data set: this new data set does not render any of the columns that were not in the original data set. This is hugely problematic as the table is essentially cleared when none of the columns are the same, and I often need to load completely different data into ui-grid in this single page app.
When the JSON is recieved I simply bind the jsonResult.results to the old $scope.myData variable that ui-grid is bound to.
I've made a plunker isolating this issue. A dataset with a "punk" column is loaded, and then clicking "swap data" will try to load a dataset with "employee" column instead of "punk". I've so far looked into directives that will refresh or reload when the $scope.myData variable changes using $watch, and looked at finding something like $scope.columnDefs to let ui-grid know. Relatively new to angular and javascript so directives are still a bit over my head.
I have updated your plunker slightly:
$scope.swapData = function() {
if ($scope.gridOpts.data === data1) {
$scope.gridOpts.columnDefs = [
{ name:'firstName' },
{ name:'lastName' },
{ name:'company' },
{ name:'employee' }
];
$scope.gridOpts.data = data2;
//punk column changes to employee
}
else {
$scope.gridOpts.columnDefs = [
{ name:'firstName' },
{ name:'lastName' },
{ name:'company' },
{ name:'punk' }
];
$scope.gridOpts.data = data1;
//employee column changes to punk
}
};
http://plnkr.co/edit/OFt86knctJxcbtf2MwYI?p=preview
Since you have the columns in your json, it should be fairly easy to do.
One additional piece that I figured out with the help of Kevin Sage's answer and the plunker example... If you are using the backward-compatible "field" attribute the swapping does not work properly when there are field name overlaps between the two sets of column definitions. The column headers and the column widths are not rendered properly in this case. Using the "name" attribute of the column definition corrects this.
$scope.swapData = function() {
if ($scope.gridOpts.data === data1) {
$scope.gridOpts.columnDefs = [
{ field:'firstName' },
{ field:'lastName' },
{ field:'company' },
{ field:'employee' }
];
$scope.gridOpts.data = data2;
//punk column changes to employee
}
else {
$scope.gridOpts.columnDefs = [
{ field:'firstName' },
{ field:'lastName' },
{ field:'company' },
{ field:'punk' }
];
$scope.gridOpts.data = data1;
//employee column changes to punk
}
};
Example here: Plunker
My solution:
$http.get('url').success(function(res) {
// clear data
gridOptions.data.length = 0;
// update data in next digest
$timeout(function() {
gridOptions.data = res;
});
});

Categories

Resources