Nativescript: RadListView, how to switch layout (listViewLayout) programatically - nativescript

I have a very common scenario when the user can switch list layout between linear/grid/staggered view by tapping an icon. Before I had 2 lists - ListView for standard list layout and RadListView for grid view. I hided and showed them depending on required "mode". But since RadListView has all required layouts theoretically I can have only one list and reuse it by switching layouts. I haven't found how to do that directly in XML (that would be the best approach if any), so I'm thinking of doing this programatically in the code behind.
Here is my try:
function _switchListViewLayout() {
const list = modal.getViewById( 'list' )
let layout
if ( list.listViewLayout instanceof ListViewLinearLayout ) {
// switch to grid
layout = new ListViewGridLayout()
layout.scrollDirection = 'vertical'
layout.itemHeight = 150
layout.spanCount = 2
}
else if ( list.listViewLayout instanceof ListViewGridLayout ) {
// switch to list
layout = new ListViewLinearLayout()
layout.scrollDirection = 'vertical'
layout.itemHeight = 66
}
list.listViewLayout = layout
list.refresh()
}
Is this a correct way or I'm doing it wrong?

Yes this is the way you can change the listViewLayout of the RadListView component. I do see that you have a call to the .refresh() method, that is not necessary you simply have to set the new value to the listViewLayout property.
You can change the in the official examples for RadListView here.

Related

Custom Cell Format ListView TornadoFx on delete item

I'm new to TornadoFx but am trying it out (also new to JavaFX by extension).
I have a listview defined as so:
private var colorList = mutableListOf<Color>
//other things in init block
colorpicker(mode = ColorPickerMode.MenuButton) {
valueProperty().onChange {
if (it != null) {
colorList.add(it)
}
}
}(Color.BLACK,Color.WHITE).observable()
listview(colorList) {
cellFormat {
text = it.toString()
style {
baseColor = it
}
}
contextmenu {
item("Delete").action {
if (selectedItem != null) {
colorList.remove(selectedItem)
}
}
}
}
//continue init block
Adding and taking away colors from the listview works just fine but the color inside the cell does not disapear if it is no longer occupied
Example of what is happening
The cellFormat function allows you to configure the list cell for each item in your list.
However, when there is no list item for a certain row, the callback is not run, so that you have no way of applying a style to an empty row using the cellFormat approach. One solution would be to implement your own ListCell and always clearing the style property of the cell, but I believe this might actually be fixed within the framework by always clearing the style property before a cell is reused. I just tried to make this change in the framework, and it fixes the issue with your code sample.
I will commit the change now, please try it out with tornadofx-1.7.17-SNAPSHOT :)

How to run javascript only after the view has loaded in Odoo 10

I installed web hide menu on https://www.odoo.com/apps/modules/8.0/web_menu_hide_8.0/
I modified to use it on Odoo 10, but the form will be adjusted to full width IF we press the hide button, if we were to change to another view after we pressed hide button, the form page will remain same as original (not full width).
So i need to adjust class "o_form_sheet" on form view after the page has been rendered. May i know how can i do that using javascript? Which class & method do i need to extend?
I'm going to answer my own question.
After some researched, i found out the best option was to inherit ViewManager widget using load_views function.
var ViewManager = require('web.ViewManager');
ViewManager.include({
load_views: function (load_fields) {
var self = this;
// Check if left menu visible
var root=self.$el.parents();
var visible=(root.find('.o_sub_menu').css('display') != 'none')
if (visible) {
// Show menu and resize form components to original values
root.find('.o_form_sheet_bg').css('padding', self.sheetbg_padding);
root.find('.o_form_sheet').css('max-width', self.sheetbg_maxwidth);
root.find('.o_form_view div.oe_chatter').css('max-width', self.chatter_maxwidth);
} else {
// Hide menu and save original values
self.sheetbg_padding=root.find('.o_form_sheet_bg').css('padding');
root.find('.o_form_sheet_bg').css('padding', '16px');
self.sheetbg_maxwidth=root.find('.o_form_sheet').css('max-width');
root.find('.o_form_sheet').css('max-width', '100%');
self.chatter_maxwidth=root.find('.o_form_view div.oe_chatter').css('max-width');
root.find('.o_form_view div.oe_chatter').css('max-width','100%');
}
return this._super.apply(this, arguments, load_fields);
},
});

Manually load kendo mobile view

I'm working on a Kendo Mobile project with a number of:
Kendo Views (external to root html)
Modal Views (in the root html).
The external files load on demand and everything works fine. But i'd like to have the same load on demand behavior for some of the modal views, because the root/based html file is becoming too large and not manageable.
Is there a way to either:
Store a modal view in an external file? If so is it possible to load via javascript syntax (app.navigate()) rather than the declarative syntax (href='externalmodal').
Manually pre-load an external view without navigating to it first.
This code lets you manually create a view:
var viewUrl = 'blahblahblah';
var element = $.parseHTML('<div data-role=view>test</div>')[0];
element.style.display = 'none';
$(document.body).append(element);
var options = $.extend({}, kendo.parseOptions(element, kendo.mobile.ui.View.fn.options));
var view = new kendo.mobile.ui.View(element, options);
view.element[0].setAttribute('data-url', viewUrl);
kendo.mobile.application.navigate(viewUrl, '');
Depending on what features you use, you may need to instead use code similar that that used for ModalView below so that Kendo creates the subclass (changes: substitute View for ModalView, substitute view for modalview, add data-url, remove call to show(), maybe check that view not already created by checking for element with matching data-url). We haven't tested setting roles.view this way, but we did something similar while testing this stuff out and it worked.
Don't try settings the options - Kendo got confused (at least trying to set useNativeScrolling didn't work, also don't try setting the options object on the subclass unless you really know what you are doing).
Caveat: This was using browserHistory:false (which disables routing) when the kendo.mobile.Application was created. The technique should still work when using browser history if you use a valid url fragment (same as would be created by Kendo for the pushstate/hashchange url).
This is a also way to cleanly subclass kendo.mobile.ui.View that works well - although you must still use data-role=view even though your subclass is a "different" component. Note that you can't just use you cant use your own subclassed component with its own name like role=myview to subclass a view because there are hard-coded checks specifically for data-role=view in the kendo codebase. Same if you wish to subclass: layout modalview drawer splitview page (amongst other hard-coded kendo ui component names - search kendo code for kendo.roleSelector - ugly). e.g.
MyView = kendo.mobile.ui.View.extend({
init: function(element, options) {
kendo.mobile.ui.View.prototype.init.apply(this, arguments);
...
var myView = new MyView('<div data-role=view>test</div>');
Why it works: The relevant function in the Kendo source code is _findViewElement which does element = this.container.children("[" + attr("url") + "='" + urlPath + "']"); to see if the view already exists for a url, before creating a new one. A unique init function is always required as it ends up being the constructor function.
If you want to subclass a modalview, you need to do something different due to the way kendo works:
var MyModalView = kendo.mobile.ui.ModalView.extend({
html: '<div data-role=modalview style="width:90%;display:none;">Foobar</div>',
init: function() {
kendo.mobile.ui.ModalView.prototype.init.apply(this, arguments);
}
});
function makeModalView() {
$(document.body).append($.parseHTML(MyModalView.prototype.html));
var roles = $.extend({}, kendo.mobile.ui.roles);
roles.modalview = MyModalView;
var modalView = kendo.initWidget($(element), {}, roles);
modalView.open();
return modalView;
}

Google Apps Script User Interface

Well, I've been reading the documentation and I believe that I'm calling functions and passing parameters correctly, but for the life of me I can't get this simple UI code to work.
I'm generating a UI for a Spreadsheet using the following code:
function checkOut() {
var app = buildUI();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function buildUI() {
var gui = UiApp.createApplication();
gui.setTitle("Check-Out/Check-In");
gui.setStyleAttribute("background", "lavender");
// Absolute panel for setting specific locations for elements
var panel = gui.createAbsolutePanel();
// Equipment ID#s Label
var equipmentIDLabel = gui.createLabel("Equipment ID#s");
equipmentIDLabel.setHorizontalAlignment(UiApp.HorizontalAlignment.CENTER);
equipmentIDLabel.setSize("20px", "125px");
equipmentIDLabel.setStyleAttributes({background: "SteelBlue", color: "white"});
// Add all components to panel
panel.add(equipmentIDLabel, 10, 0);
gui.add(panel);
return gui;
}
function getUIdata(eventInfo) {
// I know how to get the data from each element based on ID
}
It generates the Absolute Panel correctly when checkOut() is called, but the EquipmentIDLabel is never added to the panel. I am basing the code on the simplistic design I created in the GUI builder (that will be deprecated in a few days, which is why I am writing the code so that I can change it later):
So what exactly is going wrong here? If I can figure out how to add one element, I can infer the rest by looking at the docs. I've never been any good at GUI development!
You could maybe use grid as an interesting alternative... here is an example :
// define styles
var labelStyle = {background: "SteelBlue", color: "white",'textAlign':'center','line-height':'20px','vertical-align':'middle','font-family':"Arial, sans-serif",'fontSize':'10pt'};// define a common label style
var fieldStyle = {background: "white", color: "SteelBlue",'font-family':"Courrier, serif",'fontSize':'11pt'};// define a common label style
function checkOut() {
var app = buildUI();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function buildUI() {
var gui = UiApp.createApplication();
gui.setTitle("Check-Out/Check-In");
gui.setStyleAttribute("background", "lavender");
var panel = gui.createAbsolutePanel().setStyleAttribute('padding','10px');
var grid = gui.createGrid(4,2).setWidth('300').setCellPadding(10);//define grid size in number of row & cols
var equipmentID = ['equipmentIDLabel','equipmentIDLabel1','equipmentIDLabel2','equipmentIDLabel3'];// define labels in an array of strings
for(var n=0 ;n<equipmentID.length ; n++){;// iterate
var equipmentIDLabel = gui.createLabel(equipmentID[n]).setWidth('125').setStyleAttributes(labelStyle);
var equipmentIDField = gui.createTextBox().setText('Enter value here').setName(equipmentID[n]).setSize("125", "20").setStyleAttributes(fieldStyle);
grid.setWidget(n,0,equipmentIDLabel).setWidget(n,1,equipmentIDField);
}
gui.add(panel.add(grid));
return gui;
}
It looks like the absolute panel offset method is a little capricious and take control of your positioning, in my tests I have been able to position panels that are visible in the following way:
panel.add(equipmentIDLabel);
panel.add(equipmentIDField,150,0);
panel.add(otherLabel);
panel.add(otherField, 150, 20);
Try it out with trial and error, you may get the UI you need, if not I would move to an alternate layout, verticalPanel is a little better behaved and of course you can use forms as well.
Another small bug is that you inverted the length and hight in equipmentIDLabel.setSize("20px", "125px");
Let me know if I can be of more assitance
The specific problem in your code is the following line :
// Add all components to panel
panel.add(equipmentIDLabel, 10, 0);
Simply change it to : panel.add(equipmentIDLabel);
..and you will see the field (at position 0,0).
As patt0 observes, you can then add OTHER components and use positioning. It seems to be a limitation of adding the first field to an absolutePanel.
Of course, the Google Script gui is now deprecated (since December 2014) but I was interested to try your code and see that it still basically executes (as at Feb 2016).

Show different slider for different selections in dat.gui

I have a gui where the use can select different shapes to render with a dropdown. This works well. Now I wanna display a folder with some slider. The count, name and min/max values of the sliders differ in which shape is selected. How can I accomplish this with dat.gui.
Ok found a solution by adding this to the dat.GUI prototype:
dat.GUI.prototype.removeFolder = function(name) {
var folder = this.__folders[name];
if (!folder) {
return;
}
folder.close();
this.__ul.removeChild(folder.domElement.parentNode);
delete this.__folders[name];
this.onResize();
}

Resources