Need help to create a dynamic tab-bar for Ionic 3 app.
I've already created the dynamic tab-bar which receives tabs names from API, stores in storage and creates them in app after
ts:
unionTabs = [];
this.storage.get('tabs').then((tabs)=>{
tabs.forEach(title => {
switch(title){
case 'Home': this.unionTabs.push({title: title, root: HomePage, icon: 'home'})
break;
case 'Social Feed': this.unionTabs.push({title: title, root: SocialFeedPage, icon: 'pulse'})
break;
case 'Contact': this.unionTabs.push({title: title, root: ContactPage, icon: 'contacts'})
break;
case 'Mail': this.unionTabs.push({title: title, root: MailClientPage, icon: 'mail'})
break;
case 'Settings': this.unionTabs.push({title: title, root: SettingsPage, icon: 'settings'})
break;
default: alert('There is some error with the tabs!!')
}
});
})
html:
<ion-tabs *ngIf="unionTabs.length>0;else noData">
<ion-tab *ngFor="let tab of unionTabs" [root]="tab.root" [tabTitle]="tab.title" [tabIcon]="tab.icon"></ion-tab>
</ion-tabs>
But can't figure it out how to display only five (5) tabs and the last tab should display the list of other tabs. The same functionality is in the Facebook App. Unfortunately, I can't hardcoded these 5 tabs because I receiving the different tabs from a server (depends on user account)
Thank you.
Ok, I think I found the solution.
this.storage.get('tabs').then((tabs) => {
if (tabs.length < 6) {
for (let title of tabs) {
this.drawTab(title);
}
} else {
var tabNumber = 0;
for (let title of tabs) {
if (tabNumber === 4) {
this.unionTabs.push({ title: 'More', root: TabListPage, icon: 'menu' });
break
}
tabNumber++;
this.drawTab(title);
}
}
})
drawTab(tabName: string) {
switch (tabName) {
case 'Home': this.unionTabs.push({ title: tabName, root: HomePage, icon: 'home' });
break;
case 'Social Feed': this.unionTabs.push({ title: tabName, root: SocialFeedPage, icon: 'pulse' })
break;
case 'Contact': this.unionTabs.push({ title: tabName, root: ContactPage, icon: 'contacts' })
break;
case 'Mail': this.unionTabs.push({ title: tabName, root: MailClientPage, icon: 'mail' })
break;
case 'Events': this.unionTabs.push({ title: tabName, root: EventsPage, icon: 'megaphone' })
break;
case 'Settings': this.unionTabs.push({ title: tabName, root: SettingsPage, icon: 'settings' })
break;
default: alert('There is some error with the tabs!!')
}
}
And on the 'MorePage' u can do with rest of the tabs whatever you want:
listTabs = [];
this.storage.get('tabs').then((tabs)=>{
let tabCounter = 0;
for (let tab of tabs){
tabCounter++;
if(tabCounter > 4){
this.listTabs.push(tab)
}
}
})
Hope someone will find it useful as I.
Related
I am having trouble refreshing a Datatable in my Lightning Web Component after updating a record. I am calling an onclick action on a button within the row, and imperatively calling an Apex method to update that record. I then call the refreshApex() to update the data being fed into the Datatable.
However, after the refreshApex(), the tables within the for:each are not being refreshed with new data.
The records are properly modified and reflect the changes properly when refreshing the entire page.
Note: The Task object is not supported in LWC, and I cannot use the updateRecord() method to update these records.
HTML:
<template>
<template if:true="{taskCompWrapperList}">
<!--<lightning-layout multiple-rows="false" pull-to-boundary="small">-->
<template for:each="{taskCompWrapperList}" for:item="taskTemplate">
<lightning-layout-item
key="{taskTemplate.taskSectionOrder}"
size="3"
class="slds-p-around_x-small"
>
<!-- Start bear tile -->
<lightning-card title="{taskTemplate.taskSectionTitle}">
<div class="slds-m-around_medium">
<template if:true="{taskTemplate.taskList}">
<lightning-datatable
key-field="Id"
data="{taskTemplate.taskList}"
onrowaction="{handleRowAction}"
columns="{columns}"
onsave="{handleSave}"
draft-values="{draftValues}"
>
</lightning-datatable>
</template>
<template if:true="{contact.error}">
<!-- handle Apex error -->
</template>
</div>
</lightning-card>
<!-- End bear tile -->
</lightning-layout-item>
</template>
<!--</lightning-layout>-->
</template>
</template>
Javascript:
import { LightningElement, api, wire ,track} from 'lwc';
import getTaskCompWrappers from '#salesforce/apex/ENT_Task_Utility.getTaskComponentWrapper';
import updateTask from '#salesforce/apex/ENT_Task_Utility.updateTask';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '#salesforce/apex';
const COLS = [
{
type: 'button',
label: 'Complete',
typeAttributes:
{
//iconName: 'action:preview',
label: 'Complete',
name: 'Complete',
title: 'Complete',
value: 'Complete',
variant: 'brand',
alternativeText: 'Complete'
}
},
{
type: 'button-icon',
label: 'Start',
typeAttributes:
{
iconName: 'action:approval',
//label: 'Complete',
name: 'Start',
title: 'Start',
value: 'Start',
variant: 'success',
alternativeText: 'Start',
}
},
{
type: "button",
typeAttributes:
{
label: 'View',
name: 'View',
title: 'View',
disabled: false,
value: 'view',
iconPosition: 'left'
}
},
{
type: "button",
typeAttributes:
{
label: 'Edit',
name: 'Edit',
title: 'Edit',
disabled: false,
value: 'edit',
iconPosition: 'left'
}
},
//{ label: 'Complete', fieldName: 'Task_Complete__c', editable: true },
{ label: 'Status', fieldName: 'Status', type: 'picklist', editable: true },
{ label: 'Completed', fieldName: 'Completed', type: 'boolean', editable: true },
{ label: 'Owner', fieldName: 'OwnerId', editable: true },
{ label: 'Subject', fieldName: 'Subject' },
{ label: 'Due Date', fieldName: 'ActivityDate', type: 'date' }
];
export default class ENT_Task_Utility_LWC extends LightningElement {
#api objApiName;
#api recordId;
#track testMessage = 'Test Failed :c';
#track error;
#track columns = COLS;
#track draftValues = [];
taskCompWrapperList;
#track error;
//#wire(getTasks, {recordId: '$recordId'}) taskList;`
#wire(getTaskCompWrappers, {recordId: '$recordId', objApiName: '$objApiName'})
taskCompWrapperListWire({ error, data }) {
if (data) {
this.taskCompWrapperList = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.taskCompWrapperList = undefined;
}
}
updateTaskValues (taskId, taskStatus) {
// eslint-disable-next-line no-console
console.log('updateTaskValues hit');
for(var counter = 0; counter < this.taskCompWrapperList.length; counter++) {
// eslint-disable-next-line no-console
console.log('taskWrapper: ' + this.taskCompWrapperList[counter]);
for(var counter2 = 0; counter2 < this.taskCompWrapperList[counter].taskList.length; counter2++) {
// eslint-disable-next-line no-console
console.log('task: ' + this.taskCompWrapperList[counter].taskList[counter2]);
if(this.taskCompWrapperList[counter].taskList[counter2].Id == taskId)
{
this.dispatchEvent(
new ShowToastEvent({
title: 'Task Id Found!',
message: this.taskCompWrapperList[counter].taskList[counter2].Id,
variant: 'success'
})
);
this.taskCompWrapperList[counter].taskList[counter2].Status = taskStatus;
}
}
}
}
handleRowAction(event) {
//TODO
}
}
Apex methods:
#AuraEnabled(cacheable=true)
global static List<Task> getTasks(String recordId)
{
return [SELECT Id, Subject, OwnerId FROM Task WHERE WhatId = :recordId];
}
#AuraEnabled(cacheable=true)
global static List<ENT_Task_Comp_Wrapper> getTaskComponentWrapper(String recordId, String objApiName)
{
List<Task_Template__c> taskTemplateList = [SELECT Id, Task_Component_Section_Order__c, Task_Component_Section_Title__c, (SELECT Id FROM Task_Template_Items__r)
FROM Task_Template__c
WHERE Active__c = true AND sObject__c = :objApiName ORDER BY Task_Component_Section_Order__c ASC];
List<Task> taskList = [SELECT Id, Task_Template_Item__c, OwnerId, Owner.Name, Subject, Description, Status, ActivityDate, Task_Complete__c FROM TasK WHERE WhatId = :recordId];
List<ENT_Task_Comp_Wrapper> taskCompWrapperList = new List<ENT_Task_Comp_Wrapper>();
for(Task_Template__c taskTemplate : taskTemplateList)
{
ENT_Task_Comp_Wrapper taskCompWrapper = new ENT_Task_Comp_Wrapper();
taskCompWrapper.taskSectionTitle = taskTemplate.Task_Component_Section_Title__c;
taskCompWrapper.taskSectionOrder = (Integer)taskTemplate.Task_Component_Section_Order__c;
taskCompWrapper.taskList = new List<Task>();
for(Task currentTask : taskList)
{
for(Task_Template_Item__c taskTemplateItem : taskTemplate.Task_Template_Items__r)
{
if(taskTemplateItem.Id == currentTask.Task_Template_Item__c)
{
taskCompWrapper.taskList.add(currentTask);
}
}
}
taskCompWrapperList.add(taskCompWrapper);
}
System.debug(taskCompWrapperList);
return taskCompWrapperList;
}
#AuraEnabled
global static void updateTask(String taskId, String newStatus)
{
System.debug(taskId);
Task taskToUpdate = new Task(Id = taskId, Status = newStatus);
update taskToUpdate;
//update taskToUpdate;
}
#AuraEnabled
global static void updateTask(String taskId, String newStatus)
{
System.debug(taskId);
Task taskToUpdate = new Task(Id = taskId, Status = newStatus);
update taskToUpdate;
//update taskToUpdate;
}
In your JS code you have imported refreshApex
by using this line import { refreshApex } from '#salesforce/apex';
but you didn't assigned to any wire method. Hence data is not refreshed
Please refer this documentation.
To refresh a wired method, pass the argument the wired method receives (which is the wired value) to refreshApex(). In this sample code, the wired method is taskCompWrapperListWire. Hold on to the value provisioned by the wire service and pass it to refreshApex().
#wire(getTaskCompWrappers, {recordId: '$recordId', objApiName: '$objApiName'})
taskCompWrapperListWire({ error, data }) {
if (data) {
this.taskCompWrapperList = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.taskCompWrapperList = undefined;
}
}
And then use refreshApex() as below:
refreshApex(this.taskCompWrapperListWire);
Update you code as below
updateTaskValues({
taskId: this.taskId,
taskStatus: this. taskStatus
})
.then(() => {
// your code logic
refreshApex(this.taskCompWrapperListWire);
})
.catch((error) => {
this.message = 'Error received: code' + error.errorCode + ', ' +
'message ' + error.body.message;
});
you probably need to wait for next release to have a correct way to handle such situation.
You are getting record through uiRecordApi and updating through Apex if I'm correct.
Then you would need to use getRecordNotifyChange() available in Winter 21 release.
Apart from the answer provided by Sudarshan, you should also define taskCompWrapperList as a reactive property to make it rerender when the property is updated.
#track taskCompWrapperList = [];
i created one common Popup screen its used in three module but three module have different title. I didn't give if condition in title, Is possible or not anybody give solution to me.
popup code here :
function showPopup () {
$scope.data = {};
var myPopup = $ionicPopup.show({
template: '<input focus-me type="text" ng-model="data.expensetype" limit-char limit="15">',
if (vm.usertype === 'Worker') {
title: $translate.instant('{{"wtype_message" | translate}}'),
}
else if (vm.usertype === 'Buyer') {
title: $translate.instant('{{"btype_message" | translate}}'),
}
else if (vm.usertype === 'Expense') {
title: $translate.instant('{{"etype_message" | translate}}'),
}
scope: $scope,
buttons: [
{ text: $translate.instant('{{"pcancel_message" | translate}}') },
{
text: $translate.instant('{{"psave_message" | translate}}'),
type: 'button-positive',
onTap: function (e) {
if (!$scope.data.expensetype) {
e.preventDefault();
} else {
addExpenseCategory();
return $scope.data.expensetype;
}
}
},
]
});
myPopup.then(function (res) {
$log.log('Tapped!', res);
});
}
Try this:
var categorytitle = '';
$log.log('vm.usertype', vm.usertype);
switch (vm.usertype) {
case 'Farmer':
categorytitle = 'Enter coconut type';
break;
case 'Worker':
categorytitle = $translate.instant('{{"venterworktype_message" | translate}}');
break;
case 'Buyer':
categorytitle = $translate.instant('{{"venterproduct_message" | translate}}');
break;
case 'Group':
categorytitle = $translate.instant('{{"wtype_message" | translate}}');
break;
case 'Expense':
categorytitle = $translate.instant('{{"newexpensetype_message" | translate}}');
break;
}
var myPopup = $ionicPopup.show({
template: '<input focus-me type="text" ng-model="data.expensetype" limit-char limit="15">',
//title: $translate.instant('{{"penterexpensetype_message" | translate}}'),
title: categorytitle,
scope: $scope,
buttons: [
{ text: $translate.instant('{{"pcancel_message" | translate}}') },
{
text: $translate.instant('{{"psave_message" | translate}}'),
type: 'button-positive',
onTap: function (e) {
if (!$scope.data.expensetype) {
//don't allow the user to close unless he enters producttype
e.preventDefault();
} else {
addExpenseCategory();
return $scope.data.expensetype;
}
}
},
]
});
myPopup.then(function (res) {
$log.log('Tapped!', res);
});
As the title says, I need to capture the change event of a tab and show to the user a confirm message box. I achieved this but using the confirm JS native function. I'd like to perform this using ExtJS's Ext.Msg.show(), but the program flow does not stop with this way, as it does with confirm function. See below the two ways:
'Ext.Msg.show()' way:
onBeforeTabChange: function(panel, nextTab, oldTab)
{
var bReturn = true;
if (null != oldTab)
{
if(AppGlobals.isEditing=='si')
{
Ext.Msg.show(
{
title: 'Warning',
msg: 'Leave without saving changes?',
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.WARNING,
closable: false,
buttonText:
{
yes : 'Yes, sure',
no : 'No, will save changes first'
},
fn: function (buttonId)
{
if(buttonId=="yes")
{
AppGlobals.isEditing = 'no';
bReturn = true;
}
else
{
bReturn = false;
}
}
});
}
else
{
bReturn = true;
}
}
return bReturn;
}
As I said before, the code above does not stop the program flow. The alert appears but the tab changes anyway.
'confirm' way:
onBeforeTabChange: function(panel, nextTab, oldTab)
{
var bReturn = true;
if (null != oldTab)
{
if(AppGlobals.isEditing=='si')
{
bReturn = confirm('Leave without saving changes?');
if(bReturn==true)
{
AppGlobals.isEditing = 'no';
}
}
else
{
bReturn = true;
}
}
return bReturn;
}
The code above do work, and the tab does not change until user clicks on "Yes".
Any help? Thanks in advance.
Ext.Msg.show() is asynchronous and doesn't stop execution of the rest of program. The solution would be always return false from beforetabchange listener and programmatically change the tab when user press Yes.
A Sample Code: Here i have used allowChange as flag to prevent showing of message box when tab is changed programmatically. You can use you own flag here which i suppose is AppGlobals.isEditing
Ext.application({
launch: function() {
var allowChange = false;
Ext.create('Ext.tab.Panel', {
width: 300,
height: 200,
activeTab: 0,
items: [{
title: 'Tab 1',
bodyPadding: 10,
html: 'A simple tab'
},
{
title: 'Tab 2',
html: 'Another one'
}
],
renderTo: Ext.getBody(),
listeners: {
beforetabchange: function(tabPanel, nextTab, oldTab) {
var bReturn = true;
if (null != oldTab && !allowChange) {
bReturn = false;
Ext.Msg.show({
title: 'Warning',
msg: 'Leave without saving changes?',
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.WARNING,
closable: false,
buttonText: {
yes: 'Yes, sure',
no: 'No, will save changes first'
},
fn: function(buttonId) {
if (buttonId == "yes") {
allowChange = true; // to stop showing the message box again when tab is changed programmaticaly
tabPanel.setActiveTab(nextTab);
}
}
});
}
allowChange = false;
return bReturn; // always return false
}
}
});
}
});
<link rel="stylesheet" href="https://cdn.sencha.com/ext/gpl/4.1.1/resources/css/ext-all.css">
<script type="text/javascript" src="https://cdn.sencha.com/ext/gpl/4.1.1/ext-all-debug.js"></script>
Using on the dashboard example, i'm trying to generate a treelist menu, based on user privileges.
After successfully log in, the main view is generated. The main, contains in the west region the treelist menu and next to it, the data panel. The navigation is done by using hashtags. The problem apear on refresh or in the first initialization. Actually, i noticed that the navigation store is loaded after the view is rendered.
How / where do i get to load the navigation store, so on refresh or first initalization of the view, i can get it and using it to match the routes?
Thanks,
M
My main view looks like this:
Ext.define('app.view.main.Main', {
extend: 'Ext.container.Viewport',
xtype: 'app-main',
id:'app-main',
requires: [
'Ext.button.Segmented',
'Ext.list.Tree'
],
controller: 'main',
viewModel: 'main',
cls: 'sencha-dash-viewport',
itemId: 'mainView',
layout: {
type: 'vbox',
align: 'stretch'
},
listeners: {
render: 'onMainViewRender'
},
items: [
{
xtype: 'toolbar',
cls: 'sencha-dash-dash-headerbar shadow',
height: 64,
itemId: 'headerBar',
items: [
{
xtype: 'tbtext',
text: localStorage.getItem('Name'),
cls: 'top-user-name'
},
{
xtype: 'image',
cls: 'header-right-profile-image',
height: 35,
width: 35,
alt:'current user image',
src: 'resources/images/user-profile/mb.jpg'
}
]
},
{
xtype: 'maincontainerwrap',
id: 'main-view-detail-wrap',
reference: 'mainContainerWrap',
flex: 1,
items: [
{
xtype: 'treelist',
reference: 'navigationTreeList',
itemId: 'navigationTreeList',
width: 250,
expanderFirst: false,
expanderOnly: true,
ui: 'navigation',
bind: '{navItems}',
listeners: {
selectionchange: 'onNavigationTreeSelectionChange'
}
},
{
xtype: 'container',
reference: 'mainCardPanel',
flex:1,
cls: 'sencha-dash-right-main-container',
itemId: 'contentPanel',
layout: {
type: 'card',
anchor: '100%'
}
}
]
}
]
});
The viewmodel:
Ext.define('app.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main',
stores: {
navItems: {
type: 'tree',
storeId: 'NavigationTree',
name: 'NavigationTree',
root: {
expanded: true
},
autoLoad: false,
proxy: {
type: 'ajax',
url: 'php.php',
reader: {
type: 'json',
idProperty: 'id',
messageProperty: 'msg'
}
}
}
}
});
And the viewcontroller:
Ext.define('app.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
listen : {
controller : {
'#' : {
unmatchedroute : 'onRouteChange'
}
}
},
routes: {
':node': 'onRouteChange'
},
lastView: null,
setCurrentView: function(hashTag) {
hashTag = (hashTag || '').toLowerCase();
var me = this,
refs = me.getReferences(),
mainCard = refs.mainCardPanel,
mainLayout = mainCard.getLayout(),
navigationList = refs.navigationTreeList,
store = me.getViewModel().getStore('navItems');
//store = navigationList.getStore();
var node = store.findNode('routeId', hashTag) ||
store.findNode('viewType', hashTag);
var view = (node && node.get('viewType')) ,
lastView = me.lastView,
existingItem = mainCard.child('component[routeId=' + hashTag + ']'),
newView;
// Kill any previously routed window
if (lastView && lastView.isWindow) {
lastView.destroy();
}
lastView = mainLayout.getActiveItem();
if (!existingItem) {
newView = Ext.create({
xtype: view,
routeId: hashTag, // for existingItem search later
hideMode: 'offsets'
});
}
if (!newView || !newView.isWindow) {
// !newView means we have an existing view, but if the newView isWindow
// we don't add it to the card layout.
if (existingItem) {
// We don't have a newView, so activate the existing view.
if (existingItem !== lastView) {
mainLayout.setActiveItem(existingItem);
}
newView = existingItem;
}
else {
// newView is set (did not exist already), so add it and make it the
// activeItem.
Ext.suspendLayouts();
mainLayout.setActiveItem(mainCard.add(newView));
Ext.resumeLayouts(true);
}
}
navigationList.setSelection(node);
if (newView.isFocusable(true)) {
newView.focus();
}
me.lastView = newView;
},
onNavigationTreeSelectionChange: function (tree, node) {
var to = node && (node.get('routeId') || node.get('viewType'));
if (to) {
this.redirectTo(to);
}
},
onToggleNavigationSize: function () {
var me = this,
refs = me.getReferences(),
navigationList = refs.navigationTreeList,
wrapContainer = refs.mainContainerWrap,
collapsing = !navigationList.getMicro(),
new_width = collapsing ? 64 : 250;
if (Ext.isIE9m || !Ext.os.is.Desktop) {
Ext.suspendLayouts();
refs.senchaLogo.setWidth(new_width);
navigationList.setWidth(new_width);
navigationList.setMicro(collapsing);
Ext.resumeLayouts(); // do not flush the layout here...
// No animation for IE9 or lower...
wrapContainer.layout.animatePolicy = wrapContainer.layout.animate = null;
wrapContainer.updateLayout(); // ... since this will flush them
}
else {
if (!collapsing) {
// If we are leaving micro mode (expanding), we do that first so that the
// text of the items in the navlist will be revealed by the animation.
navigationList.setMicro(false);
}
// Start this layout first since it does not require a layout
refs.senchaLogo.animate({dynamic: true, to: {width: new_width}});
// Directly adjust the width config and then run the main wrap container layout
// as the root layout (it and its chidren). This will cause the adjusted size to
// be flushed to the element and animate to that new size.
navigationList.width = new_width;
wrapContainer.updateLayout({isRoot: true});
navigationList.el.addCls('nav-tree-animating');
// We need to switch to micro mode on the navlist *after* the animation (this
// allows the "sweep" to leave the item text in place until it is no longer
// visible.
if (collapsing) {
navigationList.on({
afterlayoutanimation: function () {
navigationList.setMicro(true);
navigationList.el.removeCls('nav-tree-animating');
},
single: true
});
}
}
},
onMainViewRender:function() {
if (!window.location.hash) {
this.redirectTo("dashboard");
}
},
onRouteChange:function(id){
this.setCurrentView(id);
},
onSearchRouteChange: function () {
this.setCurrentView('searchresults');
},
onSwitchToModern: function () {
Ext.Msg.confirm('Switch to Modern', 'Are you sure you want to switch toolkits?',
this.onSwitchToModernConfirmed, this);
},
onSwitchToModernConfirmed: function (choice) {
if (choice === 'yes') {
var s = location.search;
// Strip "?classic" or "&classic" with optionally more "&foo" tokens
// following and ensure we don't start with "?".
s = s.replace(/(^\?|&)classic($|&)/, '').replace(/^\?/, '');
// Add "?modern&" before the remaining tokens and strip & if there are
// none.
location.search = ('?modern&' + s).replace(/&$/, '');
}
},
onAfterRender: function(){
console.log('after render');
}
});
I kinda solve it using "before" action in router with a method that waits for the store to load.
routes: {
':node':{
before: 'wait',
action: 'onRouteChange'
}
and the method:
wait : function() {
var args = Ext.Array.slice(arguments),
action = args.pop(),
store = Ext.getStore('NavigationTree');
if (store.loading) {
store.on('load', action.resume, action);
} else {
action.resume();
}
}
In viewcontroller
//...
var me = this,
refs = me.getReferences(),
mainCard = refs.mainCardPanel,
mainLayout = mainCard.getLayout(),
navigationList = refs.navigationTreeList,
viewModel = me.getViewModel(),
vmData = viewModel.getData(),
store = navigationList.getStore(),
//store = Ext.getStore('NavigationTree'),
node = store.findNode('routeId', hashTag),
view = node ? node.get('view') : null,
lastView = vmData.currentView,
existingItem = mainCard.child('component[routeId=' + hashTag + ']'),
newView;
// BEGIN ADD THIS
if(!view) {
var viewTag = hashTag.charAt(0).toUpperCase() + hashTag.slice(1);
view = hashTag + "." + viewTag;
if(!Ext.ClassManager.getAliasesByName('Fruileg3.view.' + view)) view = '';
}
// END
// Kill any previously routed window
if (lastView && lastView.isWindow) {
lastView.destroy();
}
//...
I have implemented $expand REST service(SAP NW Gateway) which is working fine..here I am performing $exapnd of odata, and I developing my front-end using Angular.
I am struggling to read the child result-set of payload, below is my sample payload
{
d:
{
results:
[1]
0:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/MYEXPAND/HeaderDetails('4500077411')"
uri: "host:port/sap/opu/odata/sap/MYEXPAND/HeaderDetails('4500077411')"
type: "MYEXPAND.Header"
}
-
CCode: "1042"
PONumber: "4500077411"
DocType: "UB"
NavItem:
{
results:
[2]
0:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00010')"
uri: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00010')"
type: "MYEXPAND.Item"
}
-
PoNumber: "4500077411"
PoItem: "00010"
Material: "A10001"
}
-
1:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00020')"
uri: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00020')"
type: "MYEXPAND.Item"
}
-
PoNumber: "4500077411"
PoItem: "00020"
Material: "E-M-SAMS-Q001-0009"
}
-
-
}
-
}
-
-
}
-
}
in my controller I can read like $scope.resultsset= data.d.dresults, but here in Expand I need to read my child data from navitem-results for the respective PONumber results.
here is with indentation
{
d:
{
results:
[1]
0:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/MYEXPAND/HeaderDetails('4500077411')"
uri: "host:port/sap/opu/odata/sap/MYEXPAND/HeaderDetails('4500077411')"
type: "MYEXPAND.Header"
}
-
CCode: "1042"
PONumber: "4500077411"
DocType: "UB"
NavItem:
{
results:
[2]
0:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00010')"
uri: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00010')"
type: "MYEXPAND.Item"
}
-
PoNumber: "4500077411"
PoItem: "00010"
Material: "A10001"
}
-
1:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00020')"
uri: "host:port/sap/opu/odata/sap/MYEXPAND/Items(PoNumber='4500077411',PoItem='00020')"
type: "MYEXPAND.Item"
}
-
PoNumber: "4500077411"
PoItem: "00020"
Material: "E-M-SAMS-Q001-0009"
}
-
-
}
-
}
-
-
}
-
}
help me to sort this, thanks
Rajesh
resolved my self after searching few more things in google, below is the way I cracked it
<ul>
<li ng-repeat="Y in results">
<ul>
<li ng-repeat=" Z in Y.NavItem.results">
<b>PO Number </b>: {{Z.PoNumber}}
<b>PO Item </b>: {{Z.PoItem}}
<b>Material</b> : {{Z.Material}}
</li>
</ul>
</li>
</ul>
Thanks for the support
Rajesh