What is the equivalent of callback: in a web component?

Hi all,

In my Smart-Client solutions I have D3.js graphics rendered inside JavaFX views. The graphs I insert on click callbacks to Servoy, like this

      .on("click", function(d) { window.open('callback://globals.goto_order?order_id=' + d.order_id); })

I’m looking to move to NG-Client.

So, I’m putting D3.js inside a custom web component. I can construct a graph, but I need to link elements in the graph back to Servoy. I have been trying to use ‘svy-click’.
In my formname.js I have the following function:

function click_me(event) {
	application.output("TEST")
	plugins.dialogs.showErrorDialog("TEST","TEST");

}

I place my custom component on the form, attach the click_me method to the onAction event exposed y the component.

The “click me” link that is part of the html-template works fine, it brings up a dialog box and writes a message to the console.
In the D3.js code I construct two circles, each with a similar link. They don’t work. When I inspect them, they look identical to the first link that works. Yet Angular and Servoy do not seem to know they exist. How can tell Angular?
Do I need to use $compile? If so where do I insert it without making an infinite loop? Or is there a completely different way to do this…

simplegraph.html file:

<div>
	<div style="cursor: pointer;" svy-click="handlers.onActionMethodID($event)">Click me</div>
</div>

simplegraph.spec file:

{
	"name": "abcd-simplegraph",
	"displayName": "simplegraph",
	"version": 1,
	"definition": "abcd/simplegraph/simplegraph.js",
	"libraries": [{"name":"d3js.js", "version":"3.5.6", "url":"https://d3js.org/d3.v3.min.js", "mimetype":"text/javascript"}],
	"model":
	{
			"enabled" : { "type": "enabled", "blockingOn": false, "default": true, "for": ["dataProviderID","onActionMethodID"] }
	},"handlers":
	{
	         "onActionMethodID" : {

	        	"parameters": [
								{
						          "name":"event",
								  "type":"JSEvent"
								}
							 ]
	        }
	} 
}

and simplegraph.js:

var myApp = angular.module('abcdSimplegraph',['servoy']).directive('abcdSimplegraph', function($compile) {  
    return {
      restrict: 'E',
      replace: true,
      scope: {
    	  model: '=svyModel',
    	  api: "=svyApi",
     	  handlers: "=svyHandlers"
      },
      templateUrl: 'abcd/simplegraph/simplegraph.html',
      controller: function($scope, $element, $attrs) {
       },
      link: function(scope, iElement, iAttrs) {
          var svg = d3.select(iElement[0])
              .append("svg");
          
         // on window resize, re-render d3 canvas
          window.onresize = function() {
            return scope.$apply();
          };
          scope.$watch(function(){
              return angular.element(window)[0].innerWidth;
            }, function(){
              return scope.render(scope, iElement);
            }
          );

         // define render function
          scope.render = function(scope, iElement){
            // remove all previous items before render
            svg.selectAll("*").remove();
            svg.attr("width", 200)
              .attr("height", 100);
            
                 var nodes = [{"name": "foo"}, {"name": "bar"}];
                         
                var node = svg.selectAll(".node")
                 .data(nodes)
                 .enter()
                 .append("circle")
                  .attr("svy-click", "handlers.onActionMethodID($event)")
               .attr("cx", function(d,i){
                    return 50+i*50;
                })
                .attr("cy", 50)
                .attr("r", 10)
                 .attr("tooltip-append-to-body", true)
                 .attr("tooltip", function(d){
                     return d.name;
                 }).style("cursor", "hand");
        
            };
      }
    };
  });

Can you attach onClick jquery event to the element created with 3D that executes a method in your controller? Then you could check anything you wanted and call the servoy method.

You need to do that after the document is ready

Sorry, I’m a bit lost and I cannot find any complete examples on how to do this. I have trawled the source code for the Servoy components on GitHub with no luck.

The D3.js example I have used as basis is this one:

http://jsfiddle.net/JeJenny/5py6s/

I tried adding this to my D3.js code,

             .on("click", function(d) { $window.executeInlineScript(scope.model.click_me.formname, scope.model.click_me.script,[])});

but I get a

TypeError: undefined is not an object (evaluating ‘scope.model.click_me.formname’) D3.js complains. I have added the $window service.

Another option is adding a “xlink:href” attribute in D3.js code, ut I can’t work out what the link would be.

Made some progress by putting a plain-vanilla D3 on(‘click’) into the D3.js code:

               var node = svg.selectAll(".node")
                 .data(nodes)
                 .enter()
                 .append("circle")
				 .attr("id", function(d,i){
	                    return i;
	                })
				 .on("click", function(d,i) { scope.click_me(i)})
               .attr("cx", function(d,i){
                    return 50+i*50;
                })
                .attr("cy", 50)
                .attr("r", 10)
                .style("cursor", "hand");

and in the controller of my client-side logic file:

    controller: function($scope, $element, $attrs) {
      	  $scope.click_me = function(i) {
      	  		window.alert("This an important alert! " + i);
         		$scope.handlers.click_me();
      	  }
         },

The click-me handler is triggered and I see the alert in the NG-client, but the ‘$scope.handlers.click_me();’ does not trigger the click_me method on the server.
There seems to be a change in 8.3 in this area but I’m on 8.2.3…

    .on("click", function(d,i) { scope.handlers.onActionMethodID(i) })

works. BINGO!

Just make sure you don’t have any errors if the onActionMethodID has not been set. I would say that it will produce an error.

Just in case add an if sentence.

Cheers,