Passing DataTable into a UiPath WPF Form Creator activity - uipath

I am using this nuget UiPathTeam.WpfFormCreator.Activities, through which we could show a xaml form for user input by an attended robot.
I managed to correctly work through types (Text,Image,Date,...) to populate controls like TextBoxes, DatePicker, etc following the below link https://github.com/RaduPantelimon/UiPathActivities/blob/master/WpfFormCreator/XamlFormCreator.docx .Now I also need to populate a DataGrid passing a DataTable.I have done this much, but Stuck on the point where we specify the type for the DataTable. For String it is "Text", DateTime it is "Value".So far I have tried (DataTable,List,Array..) But I am getting the below error.
Screenshot of the error:
This is my xaml
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Margin="10" Width="1000" Height="1500" >
<DataGrid Name="Table" ItemsSource="{Binding}" AutoGenerateColumns="True" />
<Button Grid.Row="4" Grid.Column="1" Margin="5" HorizontalAlignment="Center" Name="submitButton" Width="100" Height="30" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">Submit</Button>
</Grid>
This is my Return Dictionary
New Dictionary( Of String, Dictionary( Of String, Object)) From {
{ "Table", New Dictionary( Of String, Object) From { { "DataTable",InvoiceDT
} } }}

Try "DataContext" as the type for passing DataTable
New Dictionary( Of String, Dictionary( Of String, Object)) From {
{ "Table", New Dictionary( Of String, Object) From { { "DataContext", InvoiceDT } } }}

Related

How to Nest List Views in NativeScript

I'm trying to display a list of items within a list of items. Basically it's a card game, where each suit is being repeated, and then each card for each suit is being repeated.
<StackLayout margin="10 0 60 0" padding="0 0">
<ListView class="list-group" [items]="hand" (itemTap)="onItemTap($event)"
(itemLoading)="onItemLoading($event)" backgroundColor="#26252A"
style="height:100%">
<ng-template let-suit="item">
<FlexboxLayout flexDirection="row">
<ScrollView orientation="horizontal">
<StackLayout height="100" orientation="horizontal" margin="2.5, 15">
<ListView class="list-group" [items]="suit.cards">
<ng-template let-card="item">
<Label [text]="card" class="card"></Label>
</ng-template>
</ListView>
</StackLayout>
</ScrollView>
</FlexboxLayout>
</ng-template>
</ListView>
</StackLayout>
And this is what my "hand" looks like:
hand: { suit: Suit, fontColor: Color, cards: string[] }[] = [
{ suit: "Red", fontColor: new Color("red"), cards: ["14", "13"] },
{ suit: "Green", fontColor: new Color("green"), cards: ["14", "13", "12", "9"] },
{ suit: "Yellow", fontColor: new Color("yellow"), cards: ["14", "13", "10", "9"] },
{ suit: "Black", fontColor: new Color("black"), cards: ["14", "13", "9"] }
];
When I run it though, I'm only getting the very first card in each suit to be displayed.
You can check it out at the playground here:
https://play.nativescript.org/?template=play-ng&id=XfogFt&v=3
(I'm new to both NaitiveScript and Angular, so I may be missing something simple)
EDIT: It is not advisable to use nested listview as this would break
the recycling and virtualization for cells that are containing a
nested listview
You don't need a scrollview inside the ng-template, if you just remove it, it will show your all the items in each row of parent list.
<ListView class="list-group" [items]="hand" (itemTap)="onItemTap($event)"
(itemLoading)="onItemLoading($event)" backgroundColor="#26252A"
style="height:100%">
<ng-template let-suit="item">
<FlexboxLayout flexDirection="row">
<!-- <ScrollView orientation="horizontal"> -->
<StackLayout height="100" orientation="horizontal" margin="2.5, 15">
<ListView class="list-group" [items]="suit.cards">
<ng-template let-card="item">
<Label [text]="card" class="card"></Label>
</ng-template>
</ListView>
</StackLayout>
<!-- </ScrollView> -->
<Label text="Label"></Label>
</FlexboxLayout>
</ng-template>
</ListView>
I have updated the playground here. You can also use the itemHeight and itemWidth properties here for size tuning.
P.S. The itemHeight and itemWidth properties are iOS specific. If not used, items are sized dynamically depending on the data coming from the source.
As #Narendra mentioned it's not recommended to use nested list views or ngFor inside template.
I guess nativescript-accordion plugin will suit your needs, it basically supports the data structure you are looking for - List Item -> List of Items (Suit -> Cards). If you like to show the items expanded upon loading, all you have to do is, populate the selectedIndexes with all indexes. There is one issue with latest version of the plugin, which can be still handled with a simple math.
Preventing collapse upon tap is still an open feature request, but possible to achieve with an override. But as far I know, this plugin could be the only viable solution for nested list views.

NativeScript/Angular - Reactive form not working when using actionbar

First I implemented the code below.
app.component.html
<StackLayout [formGroup]="form">
<label text="Name"></label>
<TextField formControlName="Name"></TextField>
<label text="Last Name"></label>
<TextField formControlName="LastName"></TextField>
<button text="save" (tap)="save()"></button>
</StackLayout>
app.component.ts
public form: FormGroup;
constructor(private fb: FormBuilder){
this.form = this.fb.group({
"Name": ["", [Validators.required]],
"LastName": ["", [Validators.required]]
});
}
public save(){
console.log(JSON.stringify(this.form.value));
}
When I run the code above, it's everything alright. I get name and lastname correctly.
The problem occurs when I try to add an action bar to this code.
app.component.html
<ActionBar title="New" class="action-bar">
<ActionItem text="save" (tap)="save()"></ActionItem>
</ActionBar>
<StackLayout [formGroup]="form">
<label text="Name"></label>
<TextField formControlName="Name"></TextField>
<label text="Last Name"></label>
<TextField formControlName="LastName"></TextField>
<button text="save" (tap)="save()"></button>
</StackLayout>
The app.component.ts remains the same.
When I run this code and tap the button inside stacklayout I get name and lastname correctly but when I tap the ActionItem I get an empty string for both name and lastname. Am I missing something?
Your code looks just fine - in fact I have re=-tested it with this test application and everything works as expected on my side.
Side note: If testing on iOS keep in mind that subsequent console logs can be printed only once if they are identical. (this) so it might be that it appears that the log is not printed when in fact the action is done.

Nativescript Listview with header and scroll entire page

I am using ListView with Header portion on top of it like below,
<StackLayout>
<StackLayout height="200">
<Label text="Header content goes in this section"></Label>
<StackLayout>
<ListView [items]='posts'>
<!-- template items goes here -->
</ListView>
</StackLayout>
When we scroll to list the header is sticky in this case.
Is there a option that scroll overrides header also ?.I mean that header also part of scroll.
Fr Angular-2 application you can now use tkTemplateKey deirective and create your own headers, footers, groups and other custom list-view elements.
Example can be found here
Here is the code for a list-view with header and groups.
page.component.html
<ListView [items]="countries" [itemTemplateSelector]="templateSelector" (itemTap)="onItemTapFirstList($event)" class="list-group" separatorColor="white">
<ng-template nsTemplateKey="header" let-header="item">
<Label [text]="header.name" class="list-group-item h3 bg-primary" isUserInteractionEnabled="false" color="white" fontSize="24"></Label>
</ng-template>
<ng-template nsTemplateKey="footer" let-footer="item">
<Label [text]="footer.name" class="list-group-item" backgroundColor="gray"></Label>
</ng-template>
<ng-template nsTemplateKey="cell" let-country="item">
<StackLayout class="list-group-item">
<Label [text]="country.name" class="list-group-item-heading"></Label>
<Label [text]="country.desc" class="list-group-item-text" textWrap="true"></Label>
</StackLayout>
</ng-template>
</ListView>
page.component.ts
#Component({
moduleId: module.id,
templateUrl: "./multi-line-grouped.component.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MultiLineGroupedListViewExampleComponent implements OnInit {
public countries: Array<any> = [];
public templateSelector = (item: any, index: number, items: any) => {
return item.type || "cell";
}
ngOnInit() {
for (let i = 0; i < mockedCounties.length; i++) {
this.countries.push(mockedCounties[i]);
}
}
onItemTapFirstList(args: ItemEventData) {
console.log(args.index);
}
}
Not sure if there's another way, but one way could be moving the header inside the listview. For that to work it needs to be in the posts Array, so you may want to transform that into some sort of wrapping class that can contain eiter a header or item row. Then create two templates inside the listview that depending on the template key render a header or an item.
For details on templates, see https://docs.nativescript.org/cookbook/ui/list-view#define-multiple-item-templates-and-an-item-template-selector-in-xml
You can use *ngFor creating the list.Here is the sample code for doing this.
<ScrollView>
<StackLayout>
//define your header over here
<Label text="hey header"></Label>
<StackLayout *ngFor="let item of <Array>">
<GridLayout columns="4*,*" rows="*,">
<Label row="0" col="0" text="hey label"></Label>
</GridLayout>
<StackLayout>
<StackLayout>
</ScollView>

Nativescript -Open SideDrawer on button click

I am using telerik ui for native script. I need a toggle button at top to open the side menu. but I am not able to call the Showdrawer() as per the docs.
What I need is on button click side menu should open. I tried calling RadSideDrawer.prototype.showDrawer(), but failed.
Is there any other side menu available for Nativescript?
main-page.xml
<Page xmlns="http://www.nativescript.org/tns.xsd" xmlns:drawer="nativescript-telerik-ui/sidedrawer" loaded="pageLoaded">
<Page.actionBar>
<ActionBar>
<android>
<NavigationButton text="Go Back" android.systemIcon="ic_menu_moreoverflow" tap="showSideDrawer" />
</android>
</ActionBar>
</Page.actionBar>
<drawer:RadSideDrawer>
<drawer:RadSideDrawer.mainContent>
<StackLayout>
<Label text="{{ mainContentText }}" textWrap="true" />
</StackLayout>
</drawer:RadSideDrawer.mainContent>
<drawer:RadSideDrawer.drawerContent>
<StackLayout cssClass="drawerContent" style="background-color:white;">
<StackLayout cssClass="headerContent">
<Label text="Header" />
</StackLayout>
<StackLayout cssClass="drawerMenuContent">
<Label text="Item 1" style="color:black;" />
<Label text="Item 2" style="color:black;" />
<Label text="Item 3" style="color:black;" />
<Label text="Item 4" style="color:black;" />
</StackLayout>
</StackLayout>
</drawer:RadSideDrawer.drawerContent>
</drawer:RadSideDrawer>
</Page>
getting-started-model.js
var observableModule = require("data/observable");
var GettingStartedViewModel = (function (_super) {
__extends(GettingStartedViewModel, _super);
function GettingStartedViewModel() {
_super.call(this);
this.set("mainContentText", "SideDrawer for NativeScript can be easily setup in the XML definition of your page by defining main- and drawer-content. The component"
+ " has a default transition and position and also exposes notifications related to changes in its state.");
}
return GettingStartedViewModel;
})(observableModule.Observable);
exports.GettingStartedViewModel = GettingStartedViewModel;
function showSideDrawer(args) {
console.log("Show SideDrawer tapped.");
// Show sidedrawer ...
_super.prototype.showDrawer.call(this);
}
exports.showSideDrawer = showSideDrawer;
main page.js
var viewModelModule = require("./getting-started-model");
function pageLoaded(args) {
console.log("Page loaded");
var page = args.object;
page.bindingContext = new viewModelModule.GettingStartedViewModel();
}
exports.pageLoaded = pageLoaded;
You can take a look at this SDK examples that show the main functionality of the RadSideDrawer. As mentioned by #R Pelzer all you need to do is get the instance of the RadSideDrawer for example by using its id:
import drawerModule = require("nativescript-telerik-ui-pro/sidedrawer");
import frameModule = require("ui/frame");
var sideDrawer: drawerModule.RadSideDrawer = <drawerModule.RadSideDrawer>(frameModule.topmost().getViewById("sideDrawer"));
and call its showDrawer() method:
sideDrawer.showDrawer();
Are you calling the showSideDrawer function from code you didn't post? Are you sure you linked the tap button?
<Button tap="showSideDrawer" text="ToggleDrawer"/>
Maybe you can try to give the sideDrawer an Id and use this code.
var drawer = frameModule.topmost().getViewById("sideDrawer");
drawer.showDrawer();
You are getting undefined because no id was assigned to the drawer so to fix your problem assign an id to the sideDrawer <drawer:RadSideDrawer id="sideDrawer"> then you can call
var frame = require('ui/frame');
var drawer = frame.topmost().getViewById("sideDrawer");
function showSideDrawer(){
drawer.showDrawer(); // i prefer using .toggleDrawerState();
};
In my case, I missed inserting , as a result, there was a missing component when toggleDrawer was being called hence the error "TypeError: Cannot read property 'toggleDrawerState' of undefined".
Try inserting all the body component of the xml file in this might solve the issue.
Happy coding :))

How do I add rows to a bound multi-column DataGrid (Silverlight 4.0)

How would I go about adding items to the DataGrid with the code below
<sdk:DataGrid AutoGenerateColumns="False" Height="294" HorizontalAlignment="Left" Margin="63,27,0,0" Name="Assignments_datagrid" VerticalAlignment="Top" Width="533" IsReadOnly="True" SelectionChanged="Assignments_datagrid_SelectionChanged">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Assignment Name" Binding="{Binding Assignment_Name}"/>
<sdk:DataGridTextColumn Header="Type" Binding="{Binding Type}"/>
<sdk:DataGridTextColumn Header="Due Date" Binding="{Binding Assignment_Due_Date}"/>
<sdk:DataGridTextColumn Header="Class Name" Binding="{Binding Course_Name}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
hmmm, I'm not sure about what your problem is but here is what I suggest :
make sure your dataGrid's "CanUserAddRows" option is set to "True"
then you have an extra line at the bottom.
If you click the rowHeader of that line, you can add a new line. This will add a new Item to your source collection
!! Be careful that for this to work, you have to make sure that the class of your source item has a constructor with no parameter (I had some trouble with the "new row" stuff before figuring this out)
e.g. :
Class Item {
public Assignment_Name { get; set; }
...
public Item() { }
...
}

Resources