Tabulator DataTreeExpanded - tabulator

How can I change the level of dataTreeStartExpanded (row,level) function of tabulator at run-time?
I want to change the level of Expand of Tree Elements via inputs from user. So I am looking to set the Option dataTreeStartExpanded "level" at run time post initialization of the table.
Is there anyway I can do it beside re-initializing the table.

You cannot change the dataTreeStartExpanded property once the table has been instantiated.
This leaves you two options, either you pass in a function to this that then calls an external function that you replace at any point:
var externalFunc = function(row, level){
return true;
}
var table = new Tabulator("#example-table", {
dataTree:true,
dataTreeStartExpanded:function(row, level){
return externalFunc(row, level);
},
});
Or you can destroy the table, and then reinstatiate it with the new function:
table.destroy();

Related

Tabulator: How to get the set of column (fields) that are currently grouped?

In tabulator we have:
table.setGroupBy("gender"); or table.setGroupBy(["gender","age"]);
I'm looking for a way to query the table and find out what that current list of groupBy is. I can't find any prototype function that seems to do this. Something like table.getGroupBy() ?
I did try iterating over columns, but can't find a function or property that will tell me this. Any idea how to accomplish this?
You should use the getGroups function:
var groups = table.getGroups();
This will return an array of Group Components, each one representing one of the top level groups of the table.
You can then iterate over these and get the fields and keys for each group using the getField and getKey functions on the component:
var groups = table.getGroups();
groups.forEach((group) => {
var key = group.getKey();
var field = group.getField();
});
If you are working in a table with nested groups then you can call the getSubGroups function on each component to get an array of the child group components for that group:
var groups = table.getGroups();
groups.forEach((group) => {
var key = group.getKey();
var field = group.getField();
var children = group.getSubGroups();
});
You could then recurse through these until you have all of the data you need.
Finally found it, not documented but hopefully it can be trusted:
table.options.groupBy

Populating a dropdown based on selection in another dropdown in ASP.NET MVC 5

hoping someone can point out where I am going wrong. I am working on an MVC 5 ASP.NET application. In my View I have a form which, amongst other controls, has 2 dropdown boxes.The first dropdown is populated with values in the Viewbag, but I want to populate the second dropdown based on the value selected in the first dropdown. I've read lots of other posts but still can't work it out.
Here is the code for the dropdowns.
#Html.DropDownList("EquipmentPortList", new SelectList(ViewBag.EquipmentPortList, "hvid", "hvnamn"), "--Select Equipment--")
#Html.DropDownList("PortConnectedList", Enumerable.Empty<SelectListItem>(), "--Select Port--")
Here is the change event code for the first dropdown :-
$(document).on('change', '#EquipmentPortList', function () {
var url = '#Url.Action("GetPortInt", "bearers")';
var ports = $('#PortConnectedList');
var id = $(this).val();
$.getJSON(url, { portid: id }, function (response) {
ports.empty();
$.each(response, function (index, item) {
ports.append($('</option>').text(item.portnamn).val(item.portid));
});
});
});
Here is the method in the controller :-
public ActionResult GetPortInt(int portid)
{
var PortConnectedList = from h in nadb.hvportar
where h.porthvid == portid && (h.portnamn.Contains("NT") || (h.portnamn.Contains("Port")) || (h.portnamn.Contains("/")))
orderby h.portid
select new { h.portid, h.portnamn };
return Json(PortConnectedList, JsonRequestBehavior.AllowGet);
}
OK, so the first dropdown populates correctly, and when I select a value I can see (using alerts) that the change event fires and the value is correctly selected.
I can see with the use of a breakpoint that the method is triggered and returns the correct data from the database, but after that I don't know what is wrong as the dropdown does not populate.
I picked up the code change event code from another post and amended it to fit my own project but I can't see what I'm missing. Thanks.
Stephen, your DotnetFiddle link actually showed me the answer. This line :-
ports.append($('</option>').text(item.portnamn).val(item.por‌​‌​tid));
Should read
ports.append($('<option></option>').text(item.portnamn).val(‌​‌​item.portid));
Once I changed that it worked. Many thanks.

Field index for queries not updating when value set programmatically

My module creates a custom content item through the controller:
private ContentItem createContentItem()
{
// Add the field
_contentDefinitionManager.AlterPartDefinition(
"TestType",
cfg => cfg
.WithField(
"NewField",
f => f
.OfType(typeof(BooleanField).Name)
.WithDisplayName("New Field"))
);
// Not sure if this is needed
_contentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.WithPart("TestType")
);
// Create new TestType item
var newItem = _contentManager.New("TestType");
_contentManager.Create(TestItem, VersionOptions.Published);
// Set the added boolean field to true
BooleanField newField = ((dynamic)newItem).TestType.NewField as BooleanField;
newField.Value = true;
// Set title (as date created, for convenience)
var time = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt", CultureInfo.InvariantCulture).Replace(':', '.');
newItem.As<TitlePart>().Title = time;
return newItem;
}
The end result of this is a new TestType item with a field that's set to true. Viewing the content item in the dashboard as well as examining ContentItemVersionRecord in the database confirms that the value was set correctly.
However, queries don't seem to work properly on fields that are set in this manner. I found the record IntegerFieldIndexRecord, which is what I assume projections use to fill query result pages. On this, the value of TestField remains at 0 (false), instead of 1 (true).
Going to the content item edit page and simply clicking 'save' updates IntegerFieldIndexRecord correctly, meaning that the value is now picked up by the query. How can the record be updated for field values set programmatically?
Relevant section of migration:
SchemaBuilder.CreateTable(typeof(TestTypePartRecord).Name, table => table
.ContentPartRecord()
);
ContentDefinitionManager.AlterTypeDefinition(
"TestType",
cfg => cfg
.DisplayedAs("Test Type")
.WithPart(typeof(TitlePart).Name)
.WithPart(typeof(ContainablePart).Name)
.WithPart(typeof(CommonPart).Name)
.WithPart(typeof(IdentityPart).Name)
);
Edit: The fix for this is to manually change the projection index record whenever changing a field value, using this call:
_fieldIndexService.Set(testResultItem.As<FieldIndexPart>(),
"TestType", // Resolves as TestTypePart, which holds the field
"newField",
"", // Not sure why value name should be empty, but whatever
true, // The value to be set goes here
typeof(bool));
In some cases a simple contentManager.Publish() won't do.
I've had a similar problem some time ago and actually implemented a simple helper service to tackle this problem; here's an excerpt:
public T GetStringFieldValues<T>(ContentPart contentPart, string fieldName)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
return this.fieldIndexService.Get<T>(fieldIndexPart, partName, fieldName, string.Empty);
}
private void SetStringFieldValue(ContentPart contentPart, string fieldName, IEnumerable<int> ids)
{
var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>();
var partName = contentPart.PartDefinition.Name;
var encodedValues = "{" + string.Join("},{", ids) + "}";
this.fieldIndexService.Set(fieldIndexPart, partName, fieldName, string.Empty, encodedValues, typeof(string));
}
I've actually built this for use with MediaLibrary- and ContentPicker fields (they encode their value as string internally), so it might not be suitable for the boolean field in your example.
But it can't be that hard to implement, just look at the existing drivers and handlers for those fields.
There are 2 ways to fix this:
1) Ensure the newly created item is getting published by calling ContentManager.Publish() as Orchard.Projections.Handlers.FieldIndexPartHandler listens to the publish event to update the FieldIndexPartRecord
2) use IFieldIndexService to update FieldIndexPartRecord manually, see implementation of Orchard.Projections.Handlers.FieldIndexPartHandler to get in idea how to do this
Hope this helps.
:edit
Due to calling Create(...Published) the ContentManager.Published() won't do anything as the item is already considered published.
You can do the following to force the publish logic to run:
bool itemPublished = newItem.VersionRecord.Published;
// unpublish item first when it is already published as ContentManager.Publish() internally first checks for published flag and when set it aborts silently
// -> this behaviour prevents calling publish listeners
if (itemPublished)
_contentManager.Unpublish(newItem);
// the following call will result in calls to IContentHandler.Publishing() / IContentHandler.Published()
_contentManager.Publish(newItem);
or just create the item as a draft and publish it when everything is setup correctly.

Using recalc function to change a field if item has weight

I currently have a recalc function that resets the shipping cost field if a line item has changed, but I really only need to do that if the item has a weight. How do I retrieve the weight of the changed line item?
Here's what I currently have:
function recalc(){
nlapiSetFieldValue('shippingcost', '0.00');
}
recalc is fired only when a change to a line item affects the Total of the transaction, and as such, may not be a reliable event for what you want to accomplish.
I would recommend against using validateLine as that event should be used to determine whether the new value for a field is valid.
I would advise you to use fieldChanged for responding to a field value that has changed. Something like:
function fieldChanged(type, name, linenum) {
if (type == 'item') {
if (name == 'item') {
handleItemChange(linenum);
}
}
}
function handleItemChange(linenum) {
var itemWeight = parseFloat(nlapiGetFieldValue('item', 'weight', linenum)) || 0;
if (itemWeight > 0) {
nlapiSetFieldValue('shippingcost', 0);
}
}
You may also want to consider the postSourcing event instead of fieldChanged, depending on which fields should actually trigger this logic.
Small segue, recalc doesn't give you a way to get the current line of the sublist, you'd need to loop through the whole sublist anytime a single line was changed.
Try validateLine, something like:
function validateLine(listType){
//To get the item weight, you could create a
//custom transaction column field that sourced the item weight.
if(nlapiGetCurrentLineItemValue(listType,'custcolitemWeight') > 0){
nlapiSetFieldValue('shippingcost','0.00')
}
//or you could source directly from the item record using nlapiLookupField
// Depending on your use case either could be appropriate
if(nlapiLookupField('item',nlapiGetCurrentLineItemValue(listType,'item'),'weight')){
nlapiSetFieldValue('shippingcost','0.00')
}
//you *need* to return true with the validate* event functions.
return true;
}
This (untested) example only handles line additions. If users are allowed to remove items, you'll need to implement a similar validateDelete that also reverts your changes.

How to create a Custom Select List for a netsuite field?

I have a field on a custom record. The name of the field is reference_code.
I want to populate "reference_code" with my own dynamic list which would be presented as a drop down to the user.
How do I do this? I defined my field as Free-Text. Do I need to keep it hidden but then show it as a drop down before I load the form?
I thought this might do something:
nlapiInsertSelectOption('custrecord_rulereferencecode', code, code, false)
But I would need to convert the field to a select?
Typically, instead of creating the field as Free-Text, you would first create a Custom List (Customization > Lists/Records/Fields > Lists > New) with all of your dropdown options.
Then you would create your field as a List/Record field and select your new Custom List as the "List/Record Type", as depicted below.
This can be done by giving a source to your drop-down menu. The source field accepts an internal id of a list. This internal id can be an in-built(provided by netSuite) or a custom list created by a user. For Eg: I have a custom list with an internal id '23' which has some list items in it, these can be populated in the drop down menu by the following syntax.
var start = function(request, response)
{
var form = nlapiCreateForm('Custom Form');
form.addField('custpage_selectfield', 'select', 'select a color', '23');//here 23 is the internal id of my list
respnose.writePage(form);
}
or you could generate you own field's dynamically using the addSelectOption() function.
var start = function(request, response)
{
var form = nlapiCreateForm('Custom Form');
var myselectfield = form.addField('custpage_selectfield', 'select', 'select a color');
myselectfield.addSelectOption('1', 'Red');//Here 1, 2 and 3 are the id's
myselectfield.addSelectOption('2', 'Green');//which are returned when the
myselectfield.addSelectOption('3', 'Blue');//form is submitted
respnose.writePage(form);
}
I solved this by creating two fields. One is created in the RecordType and will store the info. I set this as hidden. The next field, with the custom dropdown is added in user event. I then process data for my custom dynamic select list and add that to my added user event field.
Then in my change event, I set the record type field to the value selected in my dynamically added field.
Userevent
function userEventBeforeLoad(type, form, request){
if(type == "edit"){
form.addField('custpage_referencecode','select','Reference Code',null, null)
}
}
In my Client Script:
function clientFieldChanged(type, name, linenum){
if(name == 'custpage_referencecode'){
//obtain the upper case value
var codetext = nlapiGetFieldValue(name)
//make sure it hasn't been set
if (codetext != nlapiGetFieldValue('custrecord_rulereferencecode'))
{
nlapiSetFieldValue('custrecord_rulereferencecode', codetext );
}
}
return true
}

Resources