I would like to display MultiComboBox with preselected items.
As an example let's say I have three entities in my OData service:
Car (CarId, Name)
CarColors (CarId, ColorId)
AvailableCarColors (ColorId, Description)
A car can be painted using any number of available colors. Imagine a car configurator which enables you to choose colors for your car.
I would like to display MultiComboBox with items bound to AvailableCarColors and use CarColors as source of selected items.
Is it possible to perform such binding without contorller logic, only using xml view?
Example
In the example above I would like to have:
Porsche initially assigned Blue, Cyan and Magenta
Mercedes initially assigned Red
BMW initially assigned Green, Yellow, Black
Also, example utilizes JSONModel and I am trying to do the same with ODataModel.
If you have a navigation property from Car to CarColors then it's possible, however not completely without a code. At the point where you react to the change of CarId you have to make a context binding, any control can be bound to a context.
For example, suppose you have navigation property CarColors of entity Car, and also it is assumed that you use unnamed OData model, then you can bind the context in this way (for a View):
this.getView().bindObject({
path: oDataModel.createKey("/Car", { CarId: <some car id> }),
parameters: {
expand: "CarColors"
}
});
After that you can bind your MultiComboBox items in this form:
items="{CarColors}"
Note, there is no starting slash in the binding as it should take the property from the context.
If you want to show ALL colors with some of them selected then it can be done with complex binding and formatter function.
So, the MultiComboBox items should be bound to AvailableCarColors and selectedKeys should have complex binding, something like this:
selectedKeys="{
path: 'CarColors', formatter: '.formaSelectedColors'
}
formaSelectedColors has single array parameter with CarColors and must return String array with all color keys.
I have modified your JSON for correct binding, added new property called KeysSelected for selecting the colors corresponding to the car. As per the binding is concern the object related to the individual car should be inside.
Used selectedKeys property for selecting the key(colors)
<MultiComboBox ..... selectedKeys="{KeysSelected}" >
Working code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template</title>
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_belize"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
controllerName="MyController"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:f="sap.ui.layout.form">
<Shell>
<List items="{/Cars}">
<CustomListItem>
<f:SimpleForm layout="ResponsiveGridLayout" editable="true">
<Label text="{Name}" />
<MultiComboBox items="{/AvailableCarColors}" selectedKeys="{KeysSelected}" >
<core:Item key="{ColorId}" text="{Description}"/>
</MultiComboBox>
</f:SimpleForm>
</CustomListItem>
</List>
</Shell>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel"
], function (Controller, JSONModel) {
"use strict";
return Controller.extend("MyController", {
onInit : function () {
var oModel = new JSONModel({
Cars: [
{
CarId: 1,
KeysSelected : ["3", "4", "5"],
Name: "Porsche",
ToColors:[
{ CarId: 1, ColorId: 3},
{ CarId: 1, ColorId: 4},
{ CarId: 1, ColorId: 5},
]
},
{
CarId: 2,
KeysSelected : ["1"],
Name: "Mercedes",
ToColors:[
{ CarId: 2, ColorId: 1},
]
},
{
CarId: 3,
KeysSelected : ["2", "6", "7"],
Name: "BMW",
ToColors:[
{ CarId: 3, ColorId: 2},
{ CarId: 3, ColorId: 6},
{ CarId: 3, ColorId: 7},
]
},
],
AvailableCarColors: [
{ ColorId: 1, Description: 'Red' , KeysSelected : ["0", "1"]},
{ ColorId: 2, Description: 'Green' },
{ ColorId: 3, Description: 'Blue' },
{ ColorId: 4, Description: 'Cyan' },
{ ColorId: 5, Description: 'Magenta' },
{ ColorId: 6, Description: 'Yellow' },
{ ColorId: 7, Description: 'Black' },
],
CarColors: [
{ CarId: 1, ColorId: 3},
{ CarId: 1, ColorId: 4},
{ CarId: 1, ColorId: 5},
{ CarId: 2, ColorId: 1},
{ CarId: 3, ColorId: 2},
{ CarId: 3, ColorId: 6},
{ CarId: 3, ColorId: 7},
]
});
this.getView().setModel(oModel);
}
});
});
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
Output
You can use expression binding, its work for one selection
<MultiComboBox items="{/AvailableCarColors}" selectedKeys="{=${Name} === 'Porsche' ? '3': ${Name} === 'BMW' ? '2' : '1' }" >
But Iam not sure how to use for multi selection '3,4,5' and '2,6,7' dosent work may be i18n solve.
Related
How do I remove an object from an array of objects in Knockoutjs.
I am new to knockoutjs and any help will be appreciated.
A link to Jsfiddle
Line 24 in the HTML code on jsfiddle is the click binding to delete.
Line 67 in the javascript code on js fiddle is where the function to remove an object from the array is made.
I tried to use indexOf and splice Array functions on line 68 and 69 and it worked to remove but the DOM was not being updated.
Please take a look at the function removeProduct: function (product)
Html
<div>List of Product (<span data-bind="text: products().length"></span>)
</div>
<ul data-bind="foreach: products">
<li><span data-bind="text:name"></span>
Select
</li>
</ul>
<div>List of Group Ideas</div>
<ul data-bind="foreach: GroupIdeas">
<li data-bind="text:name">
<input type="button" value="Removethis" />
<input type="button" value="vote" />
</li>
</ul>
<div>List of Group members</div>
</body>
Javascript
$(function () {
var viewModel = {
productPrice: ko.observable(89),
productQty: ko.observable(2),
products: ko.observable([
{ name: "shoe", price: "788", id: 1 },
{ name: "blouse", price: "50", id: 2 },
{ name: "dress", price: "16", id: 3 },
{ name: "lipstick", price: "88", id: 4 },
{ name: "earring", price: "4", id: 5 },
{ name: "bra", price: "96", id: 6 },
{ name: "lingeringe", price: "48", id: 7 },
{ name: "neclace", price: "36", id: 8 },
]),
GroupIdeas: ko.observable([
{ name: "shoe", price: "788", prodId: 1, selectedby: "Akuba", memId:
1, votes: 3 },
{ name: "lingeringe", price: "48", prodId: 7, selectedby: "Isaac",
memId: 2, votes: 6 },
]),
GroupMember: ko.observable([
{ name: "Akuba", relation: "friend", id: 1 },
{ name: "Isaac", relation: "Husband", id: 2 },
{ name: "Ira", relation: "Sister", id: 3 },
{ name: "Davida", relation: "Mum", id: 4 }
]),
partyPerson: ko.observable("Ida"),
partyOrganiser: ko.observable("Royce"),
//addProduct = function () { /* ... leave unchanged ... */ }
removeProduct: function (product) {
/*var indexArr = viewModel.products().indexOf(product);
viewModel.products().splice(indexArr, 1)
*/
viewModel.products().remove(product)
console.log(product);
}
};
viewModel.totalAmt = ko.computed(function () {
return this.productPrice() * this.productQty();
}, viewModel);
ko.applyBindings(viewModel);
//ko.applyBindings(giftModel);
})**
Here's your updated fiddle.
You need to make products an observable array to take advantage of the remove function.
You need to make a reference to the viewmodel before you can refer to products, so your removeProduct function has to be written after the viewmodel initialisation. Similar to how you have written totalAmt.
viewModel.removeProduct = function (product) {
viewModel.products.remove(function(item){
return item.id === product.id;
});
}
I have the following map
Map testMap = {
3 : {
'order': 3,
'sample' : 'sample'
},
2 : {
'order': 2,
'sample' : 'sample'
},
1 : {
'order': 1,
'sample' : 'sample'
},
4: {
'order': 4,
'sample' : 'sample'
}
};
How i can sort it by key, if not possible by the 'order' value inside child map.
Note: the Map grows up to 100 fields.
SOLVED
i must have been tired before, but just in case someone else is looking here is my solution. Also, ordering just by key with SplayTreeMap produce a strange order like this 1,10,11,12,13,14,15,16,17,18,19,2,20,21 ...
import 'dart:collection';
void main() {
Map testMap = {
11: {
'order': '11',
'sample' : 'sample'
},
3 : {
'order': '3',
'sample' : 'sample'
},
2 : {
'order': '2',
'sample' : 'sample'
},
1 : {
'order': '1',
'sample' : 'sample'
},
4: {
'order': '4',
'sample' : 'sample'
},
31: {
'order': '31',
'sample' : 'sample'
},
21: {
'order': '21',
'sample' : 'sample'
}
};
final sorted = new SplayTreeMap.from(testMap, (a, b) => int.parse(testMap[a]['order']).compareTo(int.parse(testMap[b]['order'])));
print(sorted);
}
This is the easiest way for sorting maps by keys in dart.
var map = {
"a": 1,
"c": 3,
"b": 2,
};
void main() {
final sorted = Map.fromEntries(map.entries.toList()..sort((e1, e2) => e1.key.compareTo(e2.key)));
print(sorted);
}
A sample code on sorting Map based on it's value
import 'dart:collection';
var map = {
"a": 2,
"b": 1,
"c": -1,
};
void main() {
final sorted = new SplayTreeMap<String,dynamic>.from(map, (a, b) => map[a] > map[b] ? 1 : -1 );
print(sorted);
}
I was wondering if there is any way to have a Cascade kendo DropDownList (binded to Remote data) with client side filtering. I know that I can just use the change event of the master dropdownlist for the cascading effect and handle the case, but I wondered if there was a "kendo" way of handling this case. Possibly some parameter I could set that I have overlooked.
I think this example would help :
category: <input id="category" />
product: <input id="product" />
var category = $("#category").kendoDropDownList({
optionLabel: "Select category...",
dataSource: [
{ CategoryID: 1, CategoryName: "Beverages" },
{ CategoryID: 2, CategoryName: "Condiments" },
{ CategoryID: 3, CategoryName: "Confections" }
],
dataValueField: "CategoryID",
dataTextField: "CategoryName"
}).data("kendoDropDownList");
var product = $("#product").kendoDropDownList({
optionLabel: "Select product...",
dataSource: [
{"ProductID":35,"ProductName":"Steeleye Stout","CategoryID":1},
{"ProductID":3,"ProductName":"Aniseed Syrup","CategoryID":2},
{"ProductID":4,"ProductName":"Chef Anton's Cajun Seasoning","CategoryID":2},
{"ProductID":5,"ProductName":"Chef Anton's Gumbo Mix","CategoryID":2},
{"ProductID":6,"ProductName":"Grandma's Boysenberry Spread","CategoryID":2},
{"ProductID":8,"ProductName":"Northwoods Cranberry Sauce","CategoryID":2},
{"ProductID":16,"ProductName":"Pavlova","CategoryID":3},
{"ProductID":19,"ProductName":"Teatime Chocolate Biscuits","CategoryID":3},
{"ProductID":20,"ProductName":"Sir Rodney's Marmalade","CategoryID":3},
{"ProductID":21,"ProductName":"Sir Rodney's Scones","CategoryID":3},
{"ProductID":25,"ProductName":"NuNuCa Nuß-Nougat-Creme","CategoryID":3}
],
dataValueField: "ProductID",
dataTextField: "ProductName",
cascadeFrom: "category"
}).data("kendoDropDownList");
The loading array data example from the official documenation is just not working for me.
https://jsfiddle.net/Jngai1297/v64rwj7b/7/
html
<select class="js-example-data-array-selected">
<option value="2" selected="selected">duplicate</option>
</select
javascript
var hidata = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];
$(".js-example-data-array").select2({
data: hidata
})
$(".js-example-data-array-selected").select2({
data: hidata
})
The examples are straight out from the doc and the external resources are correct as well. Been hacking on it half the day and searched around and found nothing.
$(document).ready(function() {
var airPorts = [
{id:0,text:'airport one'},
{id:1,text:'airport two'},
{id:2,text:'airport three'},
{id:3,text:'airport four'},
];
$('.select2').select2({
data: airPorts,
});
});
I have a ui grid that contains a directive, this directive has an isolated scope and changes it's template basing on some logic.
The problem is that, when sorting (and also when PAGING), the 'logic' of the directive seems to not be correctly "re-evaluated".
In the specific example, the rightmost column should only see some "11" while if you try to sort by id (or the other fields) you'll see some spurios '0' appearing.
this is the ui:
<div ng-app="myapp">
<div ng-controller="myctrl">
<div ui-grid="gridOptions" ng-style="gridStyle"></div>
</div>
</div>
this is the js:
var myapp = angular.module('myapp', ["ngRoute", "ui.grid"])
.controller('myctrl', function($scope) {
$scope.gridOptions = {
data: [{
id: 1,
name: "Max",
other: "pippo",
number: 1
}, {
id: 2,
name: "Adam",
other: "pluto",
number: 0
}, {
id: 3,
name: "Betty",
other: "paperino",
number: 0
}, {
id: 4,
name: "Sara",
other: "fava",
number: 1
}, {
id: 5,
name: "Favonio",
other: "favona",
number: 1
}],
columnDefs: [{
field: "id",
displayName: "ID"
}, {
field: "name",
displayName: "Name"
}, {
field: "other",
displayName: "Other"
}, {
field: "number",
cellTemplate: '<div class="ui-grid-cell-contents"><mydir data="row.entity"></mydir></div>'
}]
};
}).directive("mydir", function() {
return {
restrict: 'E',
scope: {
data: "=",
},
template: '<div><label ng-if="data.number==1">{{set}}</label></div>',
link: function(scope, iElement, iAttrs) {
scope.set = -1;
if (scope.data.number == 0) {
scope.set = 00;
} else {
scope.set = 11;
}
}
}
});
and here's a fiddle:
https://jsfiddle.net/27yrut4n/
Any hint?
In the end it's a known bug:
https://github.com/angular-ui/ui-grid/issues/4869
And I solved using watch like it's said here:
Directive rendered via UI-Grid cellTemplate rendering incorrectly