Invalid filter value on Power BI chart - powerbi

I'm using a Power BI embedded chart, with filters passed in from Javascript. Because of the way the filters are defined in a database, there is a possibility that a filter could be applied with the wrong type (a string supplied for a filter that's expecting a integer, for example). If this happens then the filter is invalid, and not applied, meaning a user can potentially see information that they shouldn't.
The code for setting up the chart is:
var powerBiDashboard = powerbi.load(embedContainer, config);
powerBiDashboard.on('error', function () {
console.log('error');
});
powerBiDashboard.on('loaded', function (event) {
console.log('Loaded');
powerBiDashboard.setFilters(
[{ $schema: "http://powerbi.com/product/schema#basic",
filterType: 1,
target:
{ table: "DummyData", column: "Count" },
operator: "In",
values: ["150"],
displaySettings: { isLockedInViewMode: true }
}])
.catch(function (errors) {
console.log(errors);
});
powerBiDashboard.render();
});
(note the incorrect value of "150" for the integer filter)
This produces a chart with this in the filter:
...instead of:
If this happens, I want to not display the chart, and instead navigate away to an error page.
So... how can I tell if the filter is invalid? The error event doesn't get fired on the powerBiDashboard object, and the catch on the setFilters method call doesn't get executed either. And I can't find any properties on the powerBiDashboard object that would help.
Thanks.

First of all, Power BI JS filters are not recommended to be used with sensitive data. Instead, apply RLS on report.
As of today, the Power BI JS does not have this feature where invalid filter values throw exceptions. The Power BI Embedded team is aware of this scenario and they will add support for it in future releases.
To circumvent the scenario today, you can check the type of value before applying and accordingly show warnings/errors to users.
Visit docs for more details about applying filters using Power BI JavaScript.

Related

Power BI Embedded - Get current filters with Javascript

I have a working app based on the App Owns Data documentation & Javascript sample:
https://learn.microsoft.com/en-us/power-bi/developer/embed-sample-for-customers
https://microsoft.github.io/PowerBI-JavaScript/demo/v2-demo/index.html#
I am able to get the data out of each visualisation but I also want to know what filters are affecting it.
I can get the slicer states, but cannot get any filters applied by clicking on the charts. If you click on one datapoint, that filters the entire page. In the dashboard I can then click on the filter icon next to each chart and see 'Filters and slicers affecting this visual'.
I would really like to get this information via the JS API, but can't find it in the page.getFilters(), report.getFilters() or visual.getFilters().
Is it possible to do, and how?
For getting the filters applied on the visual, you can use the following:
async function get_visual_filters() {
// Get all the pages of the report
const pages = await report.getPages();
// Find required page
const page = pages.find((p) => p.name === "ReportSection1"); // The page in which visual is present
// Get the required visual.
const visuals = await page.getVisuals();
// Find the visual using Guid
const visual = visuals.find((v) => v.name === "VisualContainer1");
// Retrieve the filter of visual:VisualContainer1
const filters = await visual.getFilters();
console.log("The filters applied on the visual are: ", filters);
}
To get the page level filters, you can use:
const pageFilters = await page.getFilters();
To get the report level filters, you can use:
const reportFilters = await report.getFilters();
Output:
[1]: https://i.stack.imgur.com/O5q6d.png
Please refer following links:
https://learn.microsoft.com/en-us/javascript/api/overview/powerbi/get-visuals
https://learn.microsoft.com/en-us/javascript/api/overview/powerbi/control-report-filters
https://learn.microsoft.com/en-us/javascript/api/overview/powerbi/control-report-filters#get-filters

Power BI Embedded - Javascript API & Filtering

I have a working app based on the App Owns Data documentation & GitHub sample:
https://learn.microsoft.com/en-us/power-bi/developer/embed-sample-for-customers
https://github.com/Microsoft/PowerBI-Developer-Samples
My issue is with attempting to incorporate filtering as per the following:
https://github.com/Microsoft/PowerBI-JavaScript/wiki/Filters#constructing-filters
I've tried creating a filter in js in the style of:
var filter = {
$schema: "http://powerbi.com/product/schema#basic",
target: {
table: "mytable",
column: "mycolumn"
},
operator: "In",
values: [myvalue],
filterType: 1 // pbi.models.FilterType.BasicFilter
}
...and then passing that value (filter) to the "filters" property of the config object, however the filter is not applied when the report loads. (No JS errors....)
From the powerbi js wiki example:
const basicFilter: pbi.models.IBasicFilter = {
$schema: "http://powerbi.com/product/schema#basic",
target: {
table: "Store",
column: "Count"
},
operator: "In",
values: [1,2,3,4],
filterType: 1 // pbi.models.FilterType.BasicFilter,
}
I can't seem to understand how to reference :
pbi.models.IBasicFilter
(I've tried including a script reference to the models.js)
Visual studio tells me: (JS) 'Types' can only be used in a .ts file (I am new to all things TS)
There is a very similar (unanswered) post here also How to set filters in reports power BI embedded javascript
It seems we were confused about RLS vs JS filtering. We wanted the former, based on this:
https://learn.microsoft.com/en-us/power-bi/developer/embedded-row-level-security#using-rls-vs-javascript-filters

How to get item attributes via api?

We are using cloud Dynamics 365 Business Central and trying to get items with all attributes via OData.
In Microsoft documentation we found this endpoint:
api.businesscentral.dynamics.com/v1.0[our tenant id]/Sandbox/ODataV4/Company('CRONUS%20DE')/items
But unfortunately, the response does not contain item attributes and values, such as Farbe, Tiefe, etc.
Next, we tried to add new Web Services. But some of this endpoints return empty values and some of them (7506, 7507, 7508, 7510) don't work and return:
No HTTP resource was found that matches the request URI
Objects 7500, 7501, 7503 contain information about attributes. But non of them (7500 - 7510) does not contain a relation between Item, Attributes, and Values.
Maybe there is another way to get items with their attribute values? We also tried to research microsoft graph but not successful.
i am having similar troubles with this. i find the dynamics api to be exceptionally unintuitive and difficult to use. the furthest i have been able to get has been to go into the api settings for dynamics and uncover the tables for a few item attributes (i believe that the table numbers are as those below:
7500 - Item Attribute
7501 - Item Attribute Value
7502 - Item Attribute Translation
7504 - Item Attribute Value Selection
7505 - Item Attribute Value Mapping
i cannot comment on why 7503 is missing.
using 7500 as an example, when you uncover the table, the system provides a resulting endpoint (unfortunately, they always promote OData, and the outdated SOAP resource; i can't figure out why they have such a vendetta against the simple and easy-to-use REST endpoint).
https://api.businesscentral.dynamics.com/v2.0/<TENANT_ID>/<ENVIRONMENT_NAME>/ODataV4/Company('COMPANY_IDENTIFIER')/ItemAttributes
using this endpoint, you can get a listing of the attribute types themselves (e.g. let's say you've defined an attribute called 'BaseColor', you should get a result here for the name of the attribute 'BaseColor', its ID, its type, etc.),
with the ItemAttributeValues endpoint, you should get the actual attribute values that are in existence (e.g. for some item, you happened to set its 'BaseColor' attribute to 'Blue', you should get a response for this attribute value with a attribute type of 'BaseColor', a value, as 'Blue' along with the entity's ID, etc).
yet, when it comes to any instantiated attribute values for items, i can't figure out how to get the association of the attributes with those items. i expect that the "item attribute value mapping" option would be something along the lines of a item_id - attribute_id pair so that for any item in question, one could query the attributes list with something like a filter. but as you said, upon uncovering some of these elements, their respective endpoints return nothing. you get to the point where you say 'OH...AWSOME! there is a value-item mapping. that makes sense, and i can definitely use that'. a few moments later, the API spits in your face with an error, or craps on you by returning something you don't expect like an empty data set.
this api is a constant uphill battle, and totally riddled with landmines. a complete blow-me-up-pain-in-the-arse.
EDIT: 2021-06-09
i've looked into this some more. i was able to set up an export package for the various tables in question, specifically 7500, 7501, and 7505. the magical table was 7505 as it is the relationship between an attribute value and the item with which it is associated. exporting the package to excel results in good data. yet, when trying to expose this information in the OData resource, something strange happens:
in web services, i try to open up page 7505 which populates the object name as ItemAttributeValueMapping and i set the service name to 'ItemAttributeValueMapping'. This is normal.
the system complains when i fail to specify that the object type is a page. so, i go back in the line and set the selection to "Page"
when i tab through to publish the change, the object name automatically changes to 'ItemAttributeValueTranslations'.
EDIT: 2021-06-15
After a lot of fiddling about, i finally reached a point where i decided that the only way to address this was to write an al query which would expose the appropriate value-item mapping information. there is a page which provides some source code for doing this:
github AL-Code-Samples
to get something out of the API, i had to use microsoft visual studio code. there are a few good videos on how to get this up and running to get a test app working for your business central instance (i used eric hougaar's videos: Getting started with Business Central AL Development).
when you have set up your app to connect to your instance by inserting your tenant and entering your credentials, you can modify the source code as below to create a query in your system.
query 50102 "<YOUR_QUERY_NAME>"
{
QueryType = API;
APIPublisher = '<YOUR_NAME>';
APIGroup = '<YOUR_APP_GROUP>';
APIVersion = 'v1.0';
Caption = '<YOUR CAPTION>';
EntityName = '<YOUR_QUERY_NAME>';
EntitySetName = '<YOUR_API_ENDPOINT_NAME>';
elements
{
dataitem(Item; Item)
{
column(No_; "No.")
{
}
column(Description; Description)
{
}
column(Unit_Cost; "Unit Cost")
{
}
dataitem(Item_Attribute_Value_Mapping; "Item Attribute Value Mapping")
{
DataItemLink = "No." = Item."No.";
column(Item_Attribute_ID; "Item Attribute ID")
{
}
column(Item_Attribute_Value_ID; "Item Attribute Value ID")
{
}
dataitem(QueryElement6; "Item Attribute")
{
DataItemLink = ID = Item_Attribute_Value_Mapping."Item Attribute ID";
column(Name; Name)
{
}
dataItem(Queryelement10; "Item Attribute Value")
{
DataItemLink = "Attribute ID" = Item_Attribute_Value_Mapping."Item Attribute ID",
ID = Item_Attribute_Value_Mapping."Item Attribute Value ID";
column(Value; Value)
{
}
column(Numeric_Value; "Numeric Value")
{
}
}
}
}
}
}
}
once this code gets successfully uploaded to your server and returning a page (you have to wait for it), you can then use specified query number to expose the data in the API by going to business central's "web services" and adding a 'Query' to item 50102 (or whatever number you use). the endpoint will automatically be populated and you can use it to send you back the necessary JSON which will show a product, with its attribute values.
hope that helps.
You should try with below endpoint:
/v2.0/tenant_id/enviornment_name/ODataV4/Company(company_id)/Items

SpreadJS FromJson Chart load

I'm using SpreadJS v12 as a reporting tool. User will enter the page get the wanted data, create charts and save it for later use.
When user saves the report I get Json data (GC.Spread.Sheets.Workbook.toJSon) and save this Json to database and whenever someone tries to reach the same report, I get the Json from database and give it to the page (GC.Spread.Sheets.Workbook.fromJSon). Everything works fine except if there is a chart on page the data source for chart series (xValues and yValues) change. When I check Json format it looks like this: Sheet2!$B$2:$B$25 but in chart it's: Sheet2!$A$1:$A$24 . Am I doing something wrong?
By the way my serialize options: { ignoreFormula: false, ignoreStyle: false, rowHeadersAsFrozenColumns: true, columnHeadersAsFrozenRows: true, doNotRecalculateAfterLoad: false }
this.state.spread = new GC.Spread.Sheets.Workbook(document.getElementById("spreadSheetContent"), { sheetCount: 1 });
This is my save method:
var pageJson = this.state.spread.toJSON(this.serializationOption);
let self = this;
let model = {
Id: "",
Name: reportName,
Query: query,
PageJson: JSON.stringify(pageJson)
}
this.post( { model }, "Query/SaveReportTemplate")
.done(function(reply){
self.createSpreadSheet(reply);
}).fail(function(reply){
self.PopUp(reply, 4 );
});
And this is my load method:
var jsonOptions = {
ignoreFormula: false,
ignoreStyle: false,
frozenColumnsAsRowHeaders: true,
frozenRowsAsColumnHeaders: true,
doNotRecalculateAfterLoad: false
}
this.state.spread.fromJSON(JSON.parse(template.PageJson),jsonOptions);
this.state.spread.repaint();
Well after a long day, I think I've found what's causing the problem and started working around that.
Let's say we have two sheets. Sheet1's index is 0 and Sheet2's index is 1.
Because of the json serialization options like frozenColumnsAsRowHeaders and frozenRowsAsColumnHeaders until Sheet2 is painted row numbers and column number are different in the json.
If there is a formula or a chart in Sheet1 that's referencing Sheet2, their references will point to a different cell from what you set first. So always referencing the sheets that will be painted before is the way to solve this problem.

How to make Date Editable while using Glass mapper

Today i am facing one issue which has following requirement.
Date should be Editable.
Date should be in particular format.
My Code is like below which is not working.
foreach(var item in Model)
{
<div>#Editable(item, x => x.Start_Date.ToString("MMMM dd,yyyy"))</div>
}
I have tried following approach but throwing "DateParameters" namespace error.
#Editable(item, x=> x.Start_Date, new DateParameters { Format = "MMMM dd,yyyy"})
Also i have learner following thing but how can i achieve this ?
To make a field editable takes two parameters, this has been used to make the Date field editable. The first parameter instructs Glass.Mapper which field to make editable, the second parameter then specifies what the output should be when the page is not in page editing mode. This allows you to control the output of the field when in the two different modes.
Can anybody help me ?
For Experience editor mode, this works for me in razor view:
#Editable(model => model.SomeDateField, new { Format = "dd-MM-yyyy" })
Sitecore 8.2 though, with Glass 4.4.
What you want to do is to provide the default format but keep things the same for the main glass stuff. Like so:
foreach(var item in Model)
{
<div>#Editable(item, x => x.Start_Date, x=>x.Start_Date.ToString("MMMM dd,yyyy"))</div>
}
This will make the date a normal date when editing, but allow you to format it for the final page.
Usually in this case i use different code for "Normal View" and "Experience Editor", so for normal view you need only to display the date with format without making it editable, and on experience editor you need only to edit the date field the author will not care about the date format with experience editor, so your code will be like this :
foreach(var item in Model)
{
{
#if (Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
<div>#Editable(item, x => x.Start_Date)</div>
}
else
{
<div>#item.Start_Date.ToString("MMMM dd,yyyy")</div>
}
}
}
I have tried that as well but it is throwing an error like below
**Value cannot be null. Parameter name: objectToSwitchTo
at Sitecore.Diagnostics.Assert.ArgumentNotNull(Object argument, String argumentName)
at Sitecore.Common.Switcher2.Enter(TValue objectToSwitchTo)
at Glass.Mapper.Sc.GlassHtml.MakeEditable[T](Expression1 field, Expression1 standardOutput, T model, Object parameters, Context context, Database database, TextWriter writer)**
Any help on this ?