When one reorders items on a RadListView, there is a display bug that causes other items to also change place. That is a UI only bug, as the underlying data is correct.
For now the workaround I have is to handle the 'itemReordered' event and issue a `refresh()` after a short delay.
Attached is a short gif that shows the behaviour I'm seeing on an iOS emulator. (https://i.gyazo.com/24895b8b8c5c8d25722a3c2ddd635c4c.gif)
Here is my html code:
<
RadListView
row
=
"1"
[items]="listItems"
borderWidth
=
".5"
selectionBehavior
=
"Press"
(itemTap)="selectItem($event.index)"
itemReorder
=
"true"
(itemReordered)="onItemReordered($event)"
height
=
"300"
>
<
ng-template
tkListItemTemplate
let-item
=
"item"
let-i
=
"index"
>
<
Label
class
=
"nameLabel"
[text]="item" [class.highlight]="i===selectedItemIndex"
paddingLeft
=
"5"
paddingRight
=
"5"
></
Label
>
</
ng-template
>
</
RadListView
>
And the `refresh` on itemOrdered event:
itemReordered(event) {
timer.setTimeout( () => {
event.object.refresh();
this
.selectedColumnIndex = -1;
}, 50);
}
7 Answers, 1 is accepted
Thank you For your interest in UI for NativeScript.
I tested the provided scenario while using the latest nativescript-pro-ui version 3.2.0, however, was unable to recreate similar probelm. For testing, I used the example here. Also for your convenience, I am attaching gif from both simulators. It would help if you could provide sample project, which could be used for debugging and more info about your environment(node, npm, tns-core-modules, nativescript-pro-ui, CLI versions)
Regards,
nikolay.tsonev
Progress Telerik
I can confirm that your demos does work as expected, but I still see the odd behaviour on my side. Thus it probably is something on my environment. I am using TeamMaestro's seed for my project and here are the versions on my {N} project:
- node: 6.11.0
- npm: 5.5.1
- tns: 3.2.1
- angular: 4.4.6
- nativescript-pro-ui: 3.2.0
I'll try to pull off my code to a sample project and post it here.
Thanks anyway for taking the time to look into this.
Thank you for contacting us back.
Indeed It would be great if you could isolate the issue in a sample project. This will help us to investigate, what is causing this problem.
I noticed that you are using an old version of NativeScript and I would suggest upgrading to NativeScript 3.3.0 via
npm install nativescript --g
command.
I look forward to hearing from you.
Regards,
nikolay.tsonev
Progress Telerik
Hi Nikolay,
I did the NativeScript upgrade but that did not fix it. So, I created a new sample app to demo the odd behaviour, and the module/component & html are posted here below. I created the demo using "nativescript-template-ng-tutorial".
One thing I noticed that is different in my case is that I have 2 RadListViews in my page. Reordering works fine in one of the lists and the odd UI behaviour only happens on the second list! So, that might give you a lead.
When you run the sample, only the first list is visible, select any line and then the second list comes to view.
Here is the app.module.ts file, with the nativescript-ui-pro reference added:
import { NgModule, NO_ERRORS_SCHEMA } from
"@angular/core"
;
import { NativeScriptModule } from
"nativescript-angular/nativescript.module"
;
import { NativeScriptUIListViewModule } from
"nativescript-pro-ui/listview/angular"
;
import { AppComponent } from
"./app.component"
;
@NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
imports: [NativeScriptModule, NativeScriptUIListViewModule],
schemas: [NO_ERRORS_SCHEMA],
})
export class AppModule {}
And here the updated app.component.ts file:
import { Component } from
"@angular/core"
;
@Component({
selector:
"my-app"
,
templateUrl:
"app.component.html"
,
styles: [`
.highlight {
background-color:
#00FF00;
}
`]
})
export class AppComponent {
public listNames = [
'List1'
,
'List2'
,
'List3'
,
'List4'
,
'List5'
];
public selectedListIndex = -1;
public selectedListName:string =
''
;
public listItems = [
'Item1'
,
'Item2'
,
'Item3'
,
'Item4'
,
'Item5'
,
'Item6'
]
public selectedItemIndex = -1;
public selectList(index) {
this
.selectedListIndex = index;
this
.selectedListName =
this
.listNames[index];
}
public selectItem(index) {
this
.selectedItemIndex = index;
}
public onItemReordered(args) {
console.log(
"Item reordered. Old index: "
+ args.index +
" "
+
"new index: "
+ args.data.targetIndex);
}
}
And finally the html template:
<
ActionBar
title
=
"List Editor"
icon
=
""
class
=
"action-bar"
>
</
ActionBar
>
<
ScrollView
orientation
=
"vertical"
margin
=
"15"
>
<
StackLayout
>
<
StackLayout
orientation
=
"vertical"
marginBottom
=
"20"
horizontalAlignment
=
"center"
>
<
Label
text
=
"Select a Choice List"
class
=
"h3"
></
Label
>
<
GridLayout
orientation
=
"vertical"
rows
=
"auto, *, auto"
horizontalAlignment
=
"center"
width
=
"300"
>
<
RadListView
class
=
"list-group"
row
=
"1"
[items]="listNames"
borderWidth
=
".5"
selectionBehavior
=
"Press"
(itemTap)="selectList($event.index)"
height
=
"100"
itemReorder
=
"true"
>
<
ng-template
tkListItemTemplate
let-item
=
"item"
let-i
=
"index"
>
<
Label
class
=
"label"
[text]="item" [class.highlight]="i===selectedListIndex"
paddingLeft
=
"5"
paddingRight
=
"5"
></
Label
>
</
ng-template
>
</
RadListView
>
</
GridLayout
>
</
StackLayout
>
<
StackLayout
[visibility]="(selectedListName === '')?'collapse':'visible'">
<
StackLayout
class
=
"hr-light"
></
StackLayout
>
<
StackLayout
orientation
=
"vertical"
marginTop
=
"15"
marginBottom
=
"20"
horizontalAlignment
=
"center"
width
=
"500"
>
<
Label
text
=
"{{selectedListName}} items:"
textWrap
=
"true"
class
=
"h3"
></
Label
>
<
GridLayout
orientation
=
"vertical"
rows
=
"auto, *, auto"
>
<
RadListView
class
=
"list-group"
row
=
"1"
[items]="listItems"
borderWidth
=
".5"
selectionBehavior
=
"Press"
(itemTap)="selectItem($event.index)"
itemReorder
=
"true"
(itemReordered)="onItemReordered($event)"
height
=
"300"
>
<
ng-template
tkListItemTemplate
let-item
=
"item"
let-i
=
"index"
>
<
Label
class
=
"label"
[text]="item" [class.highlight]="i===selectedItemIndex"
paddingLeft
=
"5"
paddingRight
=
"5"
></
Label
>
</
ng-template
>
</
RadListView
>
</
GridLayout
>
</
StackLayout
>
</
StackLayout
>
</
StackLayout
>
</
ScrollView
>
Thank you for the attached sample code.
I tested it on my side and was able to recreate your case.
In my further research, I found that the issue is related to that fact that for the RadListView items property is bound pure JavaScript Array instead of ObservableArray.
The itemReorder functionality uses some specific of the ObservableArray, which allow using properly items reorder.
To resolve the issue I would suggest replacing the JavaScript array with the ObservableArray. For example:
import { Component } from "@angular/core";
import {ObservableArray} from "data/observable-array"
@Component({
selector: "my-app",
templateUrl: "app.component.html",
styles: [`
.highlight {
background-color: #00FF00;
}
`]
})
export class AppComponent {
public listNames = new ObservableArray(['List1','List2','List3','List4','List5']);
public selectedListIndex = -1;
public selectedListName:string = '';
public listItems = new ObservableArray(['Item1','Item2','Item3','Item4','Item5','Item6']);
public selectedItemIndex = -1;
public selectList(index) {
this.selectedListIndex = index;
this.selectedListName = this.listNamesgetItem(index);
}
public selectItem(index) {
this.selectedItemIndex = index;
}
public onItemReordered(args) {
console.log("Item reordered. Old index: " + args.index + " " + "new index: " + args.data.targetIndex);
}
}
Regards,
nikolay.tsonev
Progress Telerik
Yes Nikolay, that did the trick. Now reorder works as expected.
But, I'm now faced with another issue... how to I get the Array from an ObservableArray?
I'm using a trick here, but there's gotta be a simpler way, I suppose:
let arrayData = JSON.stringify(this.listItems.filter(() => {return true}));
I need to stringify the array data, and could not find a direct way to extract the Array.
TIA
julio
I am glad to hear that the reordering functionality now works as expected.
About the new question, indeed, the way you have shown below is one of the possible ways to stringify an observable array.
Depending on your specific case, you could also use toString method provided by ObservableArray module. For example:
var array = new ObservableArray(["test1", "test2", "test3"]);
console.log(array.toString());
Let me know if I could assist you further
Regards,
nikolay.tsonev
Progress Telerik