Is it possible to specify schema.data in a Kendo.Mvc.UI.Fluent.MultiSelectBuilder - multi-select

Using server-side filtering, I would like to respond to each request from a kendo MultiSelect widget with an object comprised of multiple properties one of which is the data items to be enumerated in the drop down list.
It looks like I need to specify schema.data. But I haven't figured out how to specify schema.data using the MVC wrappers. Is this possible or is there another way to do this?
Here's my custom MultiSelectBuilder code:
MultiSelectBuilder BuildSelector(HubAssemblyFieldEnums.FilterFields field, string placeHolder, string dataValueField, string dataTextField = default(string), string itemTemplate = default(string), string tagTemplate = default(string)) {
var name = System.Enum.GetName(typeof(HubAssemblyFieldEnums.FilterFields), field);
var multiSelect = Html.Kendo().MultiSelect()
.Name(name)
.Placeholder(placeHolder)
.HighlightFirst(true)
.Filter(FilterType.Contains)
.AutoBind(false)
.DataSource(_ => _.Read(read => {
read.Action("getFilterValues", "api/hubassembly")
.Type(HttpVerbs.Post)
.Data("function(e) { return getFilters(e, filterEnum." + name + "); }");
})
.ServerFiltering(true));
if (dataValueField != default(string)) { multiSelect.DataValueField(dataValueField); }
if (dataTextField != default(string)) { multiSelect.DataTextField(dataTextField); }
if (itemTemplate != default(string)) { multiSelect.ItemTemplate(itemTemplate); }
if (tagTemplate != default(string)) { multiSelect.TagTemplate(tagTemplate); }
return multiSelect;
}
thanks!

From Telerik tech support,
Generally speaking, this is not supported by the MultiSelect MVC
wrapper and its dataSource always expects a collection, but can be
achieved by overriding the reader.data function e.g.
multiselect.dataSource.reader.data = function (data) { return data.values};

Related

I am new to Apex development and trying to compile this code but failing

public class InstanceTriggerHandler {
public static void createInstanceHistoryRecord(Map<ID,Instance__c> newMap, Map<ID,Instance__c> oldMap) {
List<Instance_History__c > listOfIntHistoryToCreate = new List<Instance_History__c >();
List<Schema.FieldSetMember> trackedFields = SObjectType.Instance__c.FieldSets.Case_View.getFields();
if (trackedFields.isEmpty()) return;
for(Instance__c ins:newMap.values()) {
for (Schema.FieldSetMember fst : trackedFields) {
String fieldName = fst.getFieldPath();
String fieldLabel = fst.getLabel();
Instance__c oldInstance = (oldMap != null) ? oldMap.get(ins.id) : new Instance__c();
if (ins.get(fieldName) != oldInstance.get(fieldName)) {
String newValue = String.valueOf(ins.get(fieldName));
String oldValue = String.valueOf(oldInstance.get(fieldName));
if (oldValue != null && oldValue.length()>255) {
oldValue = oldValue.substring(0,255);
}
if (newValue != null && newValue.length()>255) {
newValue = newValue.substring(0,255);
}
final Instance_History__c instanceHistory = new Instance_History__c();
instanceHistory.Field__c = fieldLabel;
instanceHistory.Instance__c = ins.Id;
instanceHistory.Field_API__c = fieldName;
instanceHistory.Original_Value__c = oldValue;
instanceHistory.New_Value__c = newValue;
listOfIntHistoryToCreate.add(instanceHistory);
}
}
}
if(!listOfIntHistoryToCreate.isEmpty()) {
insert listOfIntHistoryToCreate;
}
}
}
Apex is giving me an error.
"Invalid type: Schema.Instance_History".
I already checked my custom object and it indeed has double underscores in code everywhere it is referenced. Can someone help?
Field history objects for custom objects need 2 underscores, try Instance__History. Probably easiest for you is to use http://workbench.developerforce.com/ to see all objects? You ever used "describe" operations?
https://help.salesforce.com/s/articleView?id=sf.tracking_field_history.htm&type=5
Salesforce stores an object’s tracked field history in an associated
object called StandardObjectNameHistory or CustomObjectName__History.
For example, AccountHistory represents the history of changes to the
values of an Account record’s fields. Similarly,
MyCustomObject__History tracks field history for the MyCustomObject__c
custom object.
Schema.SObjectType.Instance__c.FieldSets.Case_View.getFields();

ExtJS - Grid filter with multiple columns and multiple values

I create a grid and a toolbar with Two Menu of menuCheckItem. When i check the menuCheckItem the grid filters even with multiple values and multiple columns.
This working fine, as I have created grid 1st and then the toolbar
this.up('') // Used Instead of Ext.getCmp()
Working FIDDLE - https://fiddle.sencha.com/#view/editor&fiddle/2lop
Now I am trying to create same toolbar along with Menu separately on top 1st and then create grid at below. But while doing this, nly Multiple values is working.
I am trying to filter grid with multiple values as well as multiple columns.
Few things i tried -
// Only Filters One Value at a time with each Columns
store.queryBy(function(record,id){
return (record.get('name') == someValue && record.get('phone') == otherValue);
});
and
// Filters Many Columns with Single Value
filter.add(
property : name, phone
value : "somevalue"
operator : "OR"
);
Is there any way to implement Toolbar 1st and then grid ? And Filter grid with many values and columns simultaneously ?
In this FIDDLE i remade a function(checkchange), which is universal , can be put separately and you'll be able to attach it to every menucheckitem you create. The only thing is that if you add new menucheckitem filter you should name the menucheckitem id with the name of the columnDataIndex-Menu and add this columnDataIndex in menuFilters and thats all.
checkchange: function (checkbox, checked, eOpts) {
var menuFilters = ['name', 'phone'];
var getChecked = function (m) {
var checkedItems = [];
m.items.items.forEach(function (c) {
if (c.checked) {
checkedItems.push(c.text);
}
});
return checkedItems;
};
//
var menus = new Map();
menuFilters.forEach(function (e) {
menus.set(e, Ext.getCmp(e + '-Menu'));
});
//
var fieldValues = [];
menuFilters.forEach(function (e) {
fieldValues.push([e, getChecked(menus.get(e))]);
});
//
var store = checkbox.up('grid').store;
store.clearFilter();
//
if (fieldValues.length > 0) {
store.filterBy(function (record) {
var fV = this.fieldValues;
for (var i = 0; i < fV.length; i++) {
if (fV[i][1].length > 0) {
if (fV[i][1].indexOf(record.get(fV[i][0])) === -1) {
return false;
}
}
}
return true;
}, {
fieldValues: fieldValues
});
}
}

ExtJS 6 Use custom filter function within memory proxy

I have a store configured with memory proxy with enablePaging: true. Store's remoteFilter and remoteSort set to true so filtering and sorting requests handled by proxy.
When I filter my store by multiple fields I want to use OR condition, not AND.
Without memory proxy paging I could use remoteFilter: false and custom filter function like:
store.filterBy(function (record)
{
for (var i = 0; i < searchFields.length; ++i) {
if (record.get(searchFields[i]).toLowerCase().indexOf(searchText) !== -1) {
return true;
}
}
return false;
});
But how I can achieve this with enabled paging? Override memory proxy?
Ext.data.proxy.Memory.read use Ext.util.Filter.createFilterFn to create a filter function based on passed Ext.util.Filter[] (with property-value configs):
// Filter the resulting array of records
if (filters && filters.length) {
// Total will be updated by setting records
resultSet.setRecords(records = Ext.Array.filter(records, Ext.util.Filter.createFilterFn(filters)));
resultSet.setTotal(records.length);
}
So, if you want to use different filter logic, you can override memroy proxy read method and use custom function to create filter function:
Ext.define('MyApp.extensions.FilterMemoryProxy', {
extend: 'Ext.data.proxy.Memory',
alias: 'proxy.filtermemory',
createCustomFilterFn: function (filters)
{
if (!filters) {
return Ext.returnTrue;
}
return function (candidate)
{
var items = filters.isCollection ? filters.items : filters,
length = items.length,
i, filter;
for (i = 0; i < length; i++) {
filter = items[i];
if (!filter.getDisabled() && candidate.get(filter.getProperty()).toLowerCase().indexOf(
filter.getValue().toLowerCase()) !== -1) {
return true;
}
}
return false;
};
},
read: function (operation)
{
...
if (operation.process(resultSet, null, null, false) !== false) {
// Filter the resulting array of records
if (filters && filters.length) {
// Total will be updated by setting records
resultSet.setRecords(records = Ext.Array.filter(records, me.createCustomFilterFn(filters)));
resultSet.setTotal(records.length);
}
...
}
}
});
You can override the memory proxy to suit your needs, or, if you only wish to find a string in one of the fields specified in searchFields, you can add a 'virtual' field to the model with the convert method specified.
For example:
// Extend Ext.data.Model or create it. Dealer's choice.
Ext.define('MyLocalModel', {
extend: 'Ext.data.model',
fields: [
...
{
name: 'searchField',
type: 'string',
convert: function(value, record) {
// Get search fields somewhere
var resultArray = [];
for (var i = 0; i < searchFields.length; ++i) {
var searchField = searchFields[i];
var fieldValue = record.get(searchField);
resultArray.push(fieldValue);
}
// Join by a string that would not normally be searched
// so that field values 'foo' and 'bar' are not valid when searching 'ooba'
var result = resultArray.join('**');
return result;
}
}
]
});
All you need to do in the store then is:
store.filter('searchField', searchText);
It's not exactly what you are searching for, but it should get the job done.

Use renderer for ExtJS form field

I'm trying to create a PercentField component that extends textfield for use on ExtJS forms. The behavior I'm looking for is for the field to display percent values, e.g. 25% or 400%, but have the underlying value when the user is editing the field or the form is being submitted be a decimal, e.g. .25 or 4.
I've succeeded in getting this working by using a renderer in a grid column, (Here's a fiddle) but it doesn't look like textfield has a renderer property for using the field in basic forms. I've looked at the rawToValue and valueToRaw methods, but they don't seem to be quite what I'm looking for. Any advice?
As far as I know, there's no possibility of template for form fields. That would require to flip the input element and display a div or something, on focus and blur. That would be doable, but that implies some fine tuned CSS.
A simpler option is to implement custom valueToRaw and rawToValue methods, and let Ext handles the value lifecycle (which is really the complicated part). You'll still have to change the raw value on focus and blur, but that remains pretty straightforward.
Here's an example you can build upon (see fiddle):
Ext.define('My.PercentTextField', {
extend: 'Ext.form.field.Text',
onFocus: function() {
this.callParent(arguments);
var v = this.getValue();
if (Ext.isNumeric(v)) {
this.setRawValue(this.rawToValue(v));
}
},
onBlur: function() {
this.callParent(arguments);
var v = this.getValue();
if (Ext.isNumeric(v)) {
this.setRawValue(this.valueToRaw(v));
}
},
valueToRaw: function(v) {
return Ext.isEmpty(v)
? ''
: v * 100 + ' %';
},
rawToValue: function(v) {
// cast to float
if (!Ext.isEmpty(v)) {
var pcRe = /^(\d*(?:\.\d*)?)\s*%$/,
dcRe = /^\d*(?:\.\d*)?$/,
precision = 2,
floatValue,
match;
if (match = dcRe.test(v)) { // decimal input, eg. .33
floatValue = v * 1;
} else if (match = pcRe.exec(v)) { // % input, eg. 33 %
floatValue = match[1] / 100;
} else {
// invalid input
return undefined;
}
floatValue = Number.parseFloat(floatValue);
if (isNaN(floatValue)) {
return undefined;
} else {
return floatValue.toFixed(precision);
}
} else {
return undefined;
}
}
});

Retrieve only one item with MVVM light in Silverlight

To grab some content from a WCF Data Service into my View Model is straight forward:
public const string RequestsPropertyName = "Requests";
private DataServiceCollection<Request> _requests = null;
public DataServiceCollection<Request> Requests
{
get { return _requests; }
set
{
if (_requests == value) { return; }
var oldValue = _requests;
_requests = value;
RaisePropertyChanged(RequestsPropertyName, oldValue, value, true);
}
}
and then
Requests.LoadAsync(query);
But what if I have a property which is not a collection?
public const string RequestDetailsPropertyName = "RequestDetails";
private Request _requestDetails = null;
public Request RequestDetails
{
get { return _requestDetails; }
and so on.
Where do I get the 'LoadAsync(query)' method from?
Thank you,
Ueli
This is a pretty simple thing to do. You just need to use the DomainContext in your application. This is where you create your query from, then apply the result to your property.
Here is an example of what this might look like in your code:
void LoadRequest(int requstID)
{
var query = workContext.GetRequestByIDQuery(requestID);
workContext.Load(query, lo =>
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
if (lo.HasError)
throw lo.Error;
else
RequestDetails = lo.Entities.Single();
});
}, null);
}
In this example, the workContext object is the DomainContext. The query is an specific version on the server - you can also just contruct the query client side with:
.Where(r => r.RequestID == requestID)
After the async call, it thows any errors that occurred from the async call, and then returns the only entity returned. If you get more than 1 entity, you might use .First() instead.
If this is not enough to get you going, let me know and I can explain further.

Resources