How do I delete nested JSONModel row from a SAPUI5 table using dialog box? - json

I have a SplitApp application that consists of categories and items under each category whose json structure resembles the one below:
{
"stations":[{
station_id: "1",
station_name:"Nairobi",
items: [
{
station_id: "1",
item_id: 1,
item_name: Nairobi item A
},
{
station_id: "1",
item_id: 2,
item_name: Nairobi item B
}
,
{
station_id: "1",
item_id: 3,
item_name: Nairobi item C
}
]
},
{
station_id: "2",
station_name:"Berlin"
}]
On the master page are the stations and the detail page consists of the items displayed as a table. The ColumnListItem is active and hence it opens a dialog box where am performing other actions, one of which includes an update to MySQL database which necessitates the need for the clicked row to disappear.
The dialog box is correctly displayed with the table bindings.
I want to upon clicking a button in the dialog box to update the database, the row is deleted from the json model. My model is nested and most of the examples such as this,this,this,this appear to show deleting a row where json is non-nested.
Here is my code which deletes a whole nested structure instead of a single path of a whole nested structure. E.g.if I want to delete station_id 1-item_id 3, the whole of station_id 1 together with all the items under it is deleted.
var that = this;
var stationModel= that.getView().getModel("station")
var oModel = stationModel.getData();
var oTable = this.getView().byId("oList");
var oSelectedItemPath = oDialog.getBindingContext("station").getObject();
//the oDialog was bound through the following when a table row is clicked
//var path = evt.getSource().getBindingContext("station").getPath();
//oDialog.bindElement("station>"+path);
var index = $.map(oModel.stations, function(obj, index) {
if (obj === oSelectedItemPath) {
return index;
}
});
oModel.stations.splice(index, 1);
that.getView().getModel("station").setData(oModel);
How can I tweak the code so that I only delete the selected path only through the dialog box. Example if I delete item 3 station 1, only that item should be deleted.
No deletion is happening in the database.

Related

Responsive mat-grid-list

I intend to use a mat-grid-list with a set of responsive cards.
My problem is that I'm having errors with the breakpoints and I can't understand.
Can anyone help me?
DEMO
ts
cardLayout = this.breakpointObserver
.observe([Breakpoints.Handset, Breakpoints.Tablet])
.pipe(
map(({ matches }) => {
if (matches) {
return {
columns: 1,
miniCard: { cols: 1, rows: 1 },
chart: { cols: 1, rows: 2 },
table: { cols: 1, rows: 4 },
};
}
return {
columns: 4,
miniCard: { cols: 1, rows: 1 },
chart: { cols: 2, rows: 2 },
table: { cols: 4, rows: 4 },
};
})
);
Error
Bad Breakpoint size
That's because you have multiple subscriptions to your observable, so the values are resolved sequentially.
So when your observable emits, first subscriber (mat-grid-list) gets updated to the new layout, change detection is fired and DOM is updated. All of this happens BEFORE the mat-grid-tile gets updated, so you end up with colspans from the previous layout on children while parent has a single column.
You can use *ngIf with as syntax to store the value locally and refer to the stored value in the children elements, e.g.
<ng-container *ngIf="cardLayout | async as layout">
<mat-grid-list [cols]="layout.columns" rowHeight="200px">
<mat-grid-tile
[colspan]="layout.miniCard.cols"
[rowspan]="layout.miniCard.rows"
>
...
</mat-grid-tile>
</mat-grid-list>
</ng-container>
This allows for a single subscription (which should be more performant as well), increases readability and removes unnecessary sequential DOM updates.
Forked stackblitz here.

Hovering on one sentence should highlight matching sentence in another panel in Angular

I have 2 different JSON arrays displayed separately using a simple *ngFor loop on the same page. Ex-
json1: [ {
"order": 1,
"similarity": 0.82,
"sentence": "I would like to speak with :name:.",
"matching_sentence": "Hello, I would like to speak with Luke.",
"matching_line": 0
}]
json2: [ {
"order": 0,
"similarity": 0.82,
"sentence": "Hello, I would like to speak with Luke.",
"matching_sentence": "I would like to speak with :name:.",
"matching_line": 1,
"channel": 1,
"timeFrom": 15,
"timeTo": 20
}]
So, order property from json1 matches matching_line property of json2 and vice versa. So, what I need to achieve is that on mouse hover of json1, json2 should also be highlighted and on mouse hover of json2, json1 should also be highlighted.
This code is written in Angular 11 so, any solution whether it is by css or typescript is welcome.
You can achieve it using mouse enter leave events and keeping track of the active class
<div
*ngFor="let item of json1"
[ngClass]="{'highlight': item.order === activeHover}"
(mouseenter)="onHoverChange(item.order)"
(mouseleave)="onHoverChange(null)">
{{item.sentence}}
</div>
<div
*ngFor="let item of json2"
[ngClass]="{'highlight': item.matching_line === activeHover}"
(mouseenter)="onHoverChange(item.matching_line)"
(mouseleave)="onHoverChange(null)">
{{item.sentence}}
</div>
// in ts file
onHoverChange(value: number | null) {
this.activeHover = value;
}
Running sandbox link

NetSuite - Creating PO with line items

Using Restlets I can create any records in NetSuite. However, how do we create records with line items? I know we can use the getLineItemCount, loop through these items and use the setLineItemValue to set the line item.
What I'm not sure about is how we would pass such data to start with. So, we expect an external system to submit some data which I would then need to create POs with line items using my Restlet.
I would ideally like to test this using fire fox Poster, but not sure how to model the data. Something like this works fine to create a normal record using poster by passing data like:
{ "subsidiary" : 2, "entity" : 1084,"currency" : 2,"approvalstatus" : 2}
But how would we send line item data?
My JSon Object looks like this:
{"subsidiary" : 2,
"entity" : 1275,
"currency" : 2,
"approvalstatus" : 2,
"item": [{"item" : -3, "taxrate": 6},
{"item" : -3, "taxrate": 6}]
}
I tried getting the data out of the nested jason object with the below code but doesn't quite work...the itemid is blank
for (var x = 1; x <= jsonobject.item.length; x++)
{
var itemid = record.getLineItemValue('item', jsonobject.item['item'], x);
nlapiLogExecution('DEBUG', 'itemid', itemid)
record.setLineItemValue('item', itemid, x);
}
You could try using an array within your JSON to encapsulate the line items such as:
{"subsidiary" : 2,
"entity" : 1084,
"currency" : 2,
"approvalstatus" : 2,
"items": [{name:"item1", price: "100"},
{name:"item2", price:"200"}]
}
Your RESTlet code would have to then digest this, and call the relevant NS functions you mention.
As TonyH mentioned, your code has a bug wherein you should be getting the array index first. In addition, your index should start at 0, not 1, since you are going through a JS array, not a NetSuite sublist:
for (var x = 0; x < jsonobject.item.length; x++)
{
var itemid = jsonobject.item[x]['item'];
}
The same would go if you want to get the tax rate:
for (var x = 0; x < jsonobject.item.length; x++)
{
var taxrate = jsonobject.item[x]['taxrate'];
}

How to do a match with div with a custom-data of 'x' to a json object with the same value of 'x'?

I am not sure if this is achievable.
I have a list of li that all has a custom attribute with an unique value. I also have a JSON file that has a list of objects. Each object has a specific field that has the same value
Problem: I am trying to match the li attribute 'x' with the value 'x' inside the JSON. If that match is correct I want to grab all the fields inside the same object as 'x' and place it inside the li with attribute 'x'.
Please help, I am not sure how to start this. I will need some sample or even a jsfiddle example.
JSON Structure
[
{
"word": "hello",
"favnumber": "0070",
"item": "item1",
"color": "red"
},
{
"word": "hello world",
"favnumber": "0233070",
"item": "item2",
"color": "blue"
},
{
"word": "hello mom",
"favnumber": "0070",
"item": "item3",
"color": "pink"
},
{
"word": "hello dad",
"favnumber": "0070",
"item": "item4",
"color": "silver"
}
]
HTML Structure
<div>
<li data-item="item1">1</li>
<li data-item="item2">2</li>
<li data-item="item3">3</li>
<li data-item="item4">4</li>
</div>
HTML New Structure
<div>
<li data-item="item1">hello , 0070, item1, red</li>
<li data-item="item2">hello world, 0233070, item2, blue</li>
<li data-item="item3">hello mom, 231213, item3, pink</li>
<li data-item="item4">hello dad, 007021312, item4, silver</li>
</div>
You can split the overall task into simple sub-steps:
Query the DOM tree to extract the elements that have certain attributes (in your case, [data-item=*]).
For each of those elements, get the data-item attribute's value.
Loop through the JSON object, that represents an array, to find the element of this array respective to the DOM element found at the previous step.
Replace the DOM element's child text node to arbitrary value.
Let's walk through it.
Query the DOM tree to find elements with certain attributes
This is achieved with the help of document.querySelectorAll DOM API. The method takes the selector as its first parameter, pretty similar to what you'd write in CSS:
var items = document.querySelectorAll('[data-item]');
Now, inside items variable, you have a NodeList of elements. First step done.
Get the attribute value for every element
This is simple and can be done with something like
var name = items[0].getAttribute('data-item');
Now the name var stores a string that represents the [data-item]'s attribute value.
Since you have an array of NodeList elements, you have to loop through it:
for (var e in items) {
var element = items[e];
var name = element.getAttribute('data-item');
//...
}
Find the element in data array by element's property value
Now you have to put a loop into a loop so you can find an element that concurs with the element.
Like this:
for (var e in items) {
var element = items[e];
var name = element.getAttribute('data-item');
for (var i in data) {
var item = data[i];
// ...
}
}
Here, the item variable stores an object, one of many within the initial JSON array (named data in this particular example).
Next, you have to check if the item is one you need or not. In you case,
if (name == item.item) {
//...
}
because item's property item stores the value that has to concur with the value of [data-item] attribute of the DOM element.
Now, finally...
Replace the value
You may need something more specific to your task, but this example shows a simple element.innerText replacement.
Let's pretend you're within the if statement and its condition evaluated to true. Next, you want to do something like
var text = [];
text.push(item.word);
text.push(item.favnumber);
text.push(item.item);
text.push(item.color);
element.innerText = text.join(", ");
And that's it, basically.
You can see how the whole snippet works in this fiddle: http://jsfiddle.net/3r4rmLth/

Filtering a dropdown in Angular

I have a requirement for a select html element that can be duplicated multiple times on a page. The options for these select elements all come from a master list. All of the select elements can only show all of the items in the master list that have not been selected in any of the other select elements unless they just were duplicated.
When you select a new item from a duplicated select element, it seems to select the option after the one you selected even though the model still has the correct one set. This always seems to happen in IE11 and it happens sometimes in Chrome.
I realize this sounds convoluted, so I created a jFiddle example.
Try these steps:
Select Bender
Click the duplicate link
Select Fry (on the duplicated select)
Notice that the one that is selected is Leela but the model still has Fry (id:2) as the one selected
Can anyone tell me how I might get around this or what I might be doing wrong?
Here is the relevant Angular code:
myapp.controller('Ctrl', function ($scope) {
$scope.selectedIds = [{}];
$scope.allIds = [{ name: 'Bender', value: 1},
{name: 'Fry', value: 2},
{name: 'Leela', value: 3 }];
$scope.dupDropDown = function(currentDD) {
var newDD = angular.copy(currentDD);
$scope.selectedIds.push(newDD);
}
});
angular.module('appFilters',[]).filter('ddlFilter', function () {
return function (allIds, currentItem, selectedIds) {
//console.log(currentItem);
var listToReturn = allIds.filter(function (anIdFromMasterList) {
if (currentItem.id == anIdFromMasterList.value)
return true;
var areThereAny = selectedIds.some(function (aSelectedId) {
return aSelectedId.id == anIdFromMasterList.value;
});
return !areThereAny;
});
return listToReturn;
}
});
And here is the relevant HTML
<div ng-repeat="aSelection in selectedIds ">
Duplicate
<select ng-model="aSelection.id" ng-options="a.value as a.name for a in allIds | ddlFilter:aSelection:selectedIds">
<option value="">--Select--</option>
</select>
</div>
Hi I have just made a small change in your dupDropDown function as follows
$scope.dupDropDown = function(currentDD) {
$scope.selectedIds.push({});
}
Please check if this works for you.