Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
Anonymous
Not applicable

Angular custom visual

Can we use angular 8+ to create custom visulas. I could see links for creating custom visual in React. Similarly can we create a custom visual in angular

1 ACCEPTED SOLUTION

Hi @Anonymous,

I haven't personally unpacked this partcular pattern until you asked, as it's just works for me, but having done so (and thanks very much for asking, as it was quite a fun exercise), my understanding is as follows:

  • We have two objects available to us in a React component that we can use to manage it: props and state.
  • props are passed in upon creation/re-render, whereas state is managed internally to the component.
  • In this example, the React component is instantiated in the visual's constructor method, meaning that there is only a chance to set its props when the visual is added to the canvas or its page is opened.
  • This will be done for efficiency, i.e. it makes sense to only create the "app"-level component once rather than re-render it each time the visual updates.
  • However, this is too soon in the visual's lifecyle to be able to get the info we need from the update method, such as the dataView, viewport etc.
  • It's also not really the "React way" to destroy and create elements on changes.
  • So in this example, the component props are inaccessible in the visual's update method, so the only way to get objects into our component is to manipulate the state externally. Which we techincally should not be doing. But we have to.

Your posted code snippet doesn't include the overloaded React methods, so let's add them from the example so we can round this out:

 

    private static updateCallback: (data: object) => void = null;

    public static update(newState: State) {
        if(typeof ReactCircleCard.updateCallback === 'function'){
            ReactCircleCard.updateCallback(newState);
        }
    }

    public componentWillMount() {
        ReactCircleCard.updateCallback = (newState: State): void => { this.setState(newState); };
    }

    public componentWillUnmount() {
        ReactCircleCard.updateCallback = null;
    }

 

If we think about this in terms of component lifecycle, what's happening here is as follows:

  1. If called statically, the updateCallback method doesn't do anything if invoked, because the component will have no state.
  2. When the component is about to mount (i.e. when the visual constructor method calls it) and React invokes componentWillMount, this overloads the previously void/null updateCallback method to now trigger the component's setState method from within by assigning it the fat arrow function.
  3. The component's update function will now pass through the state we supply from our visual's update method into the overloaded updateCallback function and this will update the component state correctly. Similarly, if this function is called statically, it won't do anything as the updateCallback is void/null at this point.
  4. When the visual is unloaded/destroyed, the componentWillUnmount method (triggered by React) will reset the overloaded updateCallback function to null again.

If you want to unpack this further or get an explanation for the rationale, it'll be best to follow up with the team on the previously supplied email and hopefully they can clarify further. Please share if you find anything out 🙂


One thing I have found with using this in the real world is, if you need to add properties to the component State interface that are not part of the visual's update method, it's handy to modify the update function's signature to accept <Partial>State as follows:

 

    public static update(newState: <Partial>State) {
        /** function code as before */
    }

 

The alternative is to declare properties that aren't available to be supplied from the visual's update method as optional (with a ?) in the State interface, e.g.:

 

export interface State {
    textLabel: string,
    textValue: string,
    internalStateValue?: string
}

 

The latter way adds the overhead of having to check each optional property whenever you need to use it, so I prefer the former as I at least know that my initial state is always going to be correct when the visual instantiates.

Regards,

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




View solution in original post

4 REPLIES 4
dm-p
Super User
Super User

Hi @Anonymous,

I'm more of a React person, so haven't used Angular beyond auditioning it some years back, but as you can install Angular via npm and it uses the latest ES6 imports, you will be able to use it in custom visuals. You would need to ensure that you can fit it into the current visual.ts entry points, but this is basically how custom visuals with React are done and the example you've found is documented:

  • constructor instantiates DOM
  • update handles changes to the components

I suspect you would also need to set up your tsconfig appropriately, and possibly Webpack depending on how you need to bundle your project up.

I've adopted a similar approach with writing visuals for clients that essentially wrap other charting libraries such as Vega, Highcharts and amCharts - while these aren't as fully-featured as React/Angular, you use the visual.ts methods to manage the brokering of data from your model to the rest of your code - here's a shareable example using Vega.

Your best bet might be to contact the team - pbicvsupport@microsoft.com - to see if there are any specific things to consider with this approach for Angular.

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




Anonymous
Not applicable

Thats great thanks I will try using react as It has a simpler setup without webpacks and tsconfig. I looked into the titorial and came accross this line of code which I am trying to understand. It would be helpfull if you could explain it

 

    private static updateCallback: (data: object) => void = null;

    public static update(newState: State) {
        if(typeof ReactCircleCard.updateCallback === 'function'){
            ReactCircleCard.updateCallback(newState);
        }
    }

 

We have declared updateCallback and checked if it is a function type inside update method. may I know why ?

Hi @Anonymous,

I haven't personally unpacked this partcular pattern until you asked, as it's just works for me, but having done so (and thanks very much for asking, as it was quite a fun exercise), my understanding is as follows:

  • We have two objects available to us in a React component that we can use to manage it: props and state.
  • props are passed in upon creation/re-render, whereas state is managed internally to the component.
  • In this example, the React component is instantiated in the visual's constructor method, meaning that there is only a chance to set its props when the visual is added to the canvas or its page is opened.
  • This will be done for efficiency, i.e. it makes sense to only create the "app"-level component once rather than re-render it each time the visual updates.
  • However, this is too soon in the visual's lifecyle to be able to get the info we need from the update method, such as the dataView, viewport etc.
  • It's also not really the "React way" to destroy and create elements on changes.
  • So in this example, the component props are inaccessible in the visual's update method, so the only way to get objects into our component is to manipulate the state externally. Which we techincally should not be doing. But we have to.

Your posted code snippet doesn't include the overloaded React methods, so let's add them from the example so we can round this out:

 

    private static updateCallback: (data: object) => void = null;

    public static update(newState: State) {
        if(typeof ReactCircleCard.updateCallback === 'function'){
            ReactCircleCard.updateCallback(newState);
        }
    }

    public componentWillMount() {
        ReactCircleCard.updateCallback = (newState: State): void => { this.setState(newState); };
    }

    public componentWillUnmount() {
        ReactCircleCard.updateCallback = null;
    }

 

If we think about this in terms of component lifecycle, what's happening here is as follows:

  1. If called statically, the updateCallback method doesn't do anything if invoked, because the component will have no state.
  2. When the component is about to mount (i.e. when the visual constructor method calls it) and React invokes componentWillMount, this overloads the previously void/null updateCallback method to now trigger the component's setState method from within by assigning it the fat arrow function.
  3. The component's update function will now pass through the state we supply from our visual's update method into the overloaded updateCallback function and this will update the component state correctly. Similarly, if this function is called statically, it won't do anything as the updateCallback is void/null at this point.
  4. When the visual is unloaded/destroyed, the componentWillUnmount method (triggered by React) will reset the overloaded updateCallback function to null again.

If you want to unpack this further or get an explanation for the rationale, it'll be best to follow up with the team on the previously supplied email and hopefully they can clarify further. Please share if you find anything out 🙂


One thing I have found with using this in the real world is, if you need to add properties to the component State interface that are not part of the visual's update method, it's handy to modify the update function's signature to accept <Partial>State as follows:

 

    public static update(newState: <Partial>State) {
        /** function code as before */
    }

 

The alternative is to declare properties that aren't available to be supplied from the visual's update method as optional (with a ?) in the State interface, e.g.:

 

export interface State {
    textLabel: string,
    textValue: string,
    internalStateValue?: string
}

 

The latter way adds the overhead of having to check each optional property whenever you need to use it, so I prefer the former as I at least know that my initial state is always going to be correct when the visual instantiates.

Regards,

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




Anonymous
Not applicable

Thanks for the detailed explanation @dm-p . It was nice to know the reason for the updateCallback implementation.

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.

Top Kudoed Authors