Office add-in - Ribbon FunctionName does not seem to support calling a method from class - office365api

In the ribbon manifest, I can declare a function to execute when a ribbon button is clicked. For example,
<Action xsi:type="ExecuteFunction">
<FunctionName>doSomething</FunctionName>
</Action>
However, if I have a typescript file that has the following definition:
class MyFunctions {
public static doSomething(){
Office.context.ui.displayDialogAsync("https://localhost:44337/index.html",
{ height: 50, width: 50 }
}
}
The following would not work:
<Action xsi:type="ExecuteFunction">
<FunctionName>MyFunctions.doSomething</FunctionName>
</Action>
It's as if it does not recognize dotted names in the manifest file which in this case is ClassName.FunctionName.

MyFunctions.doSomething doesn't work because TypeScript compiler translates to it to a function (i.e. typeof MyFunctions == 'function')
Currently Office Add-in manifest only supports:
Execute a global function
Execute a member function within an "object".
Therefore, if MyFunctions is an object, the manifest will work. Here is one example:
var MyFunctions = {
doSomething: function() {}
};
Hopefully this problem will be fixed in the next release. Thanks.

Functions called by add-in commands must be global for now. In your case the function doesn't execute because it's defined as part of the MyFunctions class.
We realize it makes sense to permit the structure you describe here, so we're working on a fix to allow it in the future. Thank you!

Related

Genexus Extensions SDK - Where can I find the avaliable Menu Context strings?

Im trying to use the Genexus Extensions SDK to place buttons on the IDE, in this case, i want to place it in the "context" menu, avaliable only in objects of type "Webpanel/Webcomponent" and "Transaction", Just like WorkWithPlus does here:
So far, digging up into the avaliable documentation, i've noticed that you need tu put the context type string into the xml tag and the GUID of the package that you're aiming to add the menu item, such as below in GeneXusPackage.package:
The Context ID above will add the item into the "Folder View" Context.
My questions:
Where can I find a list with all the possible ID Context strings?
What is that package attribute for, where can i get it's possible values?
I am using the SDK for Genexus 16 U11
I'm sorry to say that there is no extensive list of all the menus available. I'd never thought of it until now, and I see how it could be useful, so we'll definitely consider making it part of the SDK so that any package implementor may use it for reference.
In the meantime, in order to add a new command in the context menu you mentioned, you have to add it to the command group that is listed as part of that menu. That group is KBObjectGrp which is provided by the core shell package whose id is 98121D96-A7D8-468b-9310-B1F468F812AE.
First define your command in your .package file inside a Commands section:
<Commands>
<CommandDefinition id='MyCommand' context='selection'/>
</Commands>
Then add it to the KBObjectGrp mentioned earlier.
<Groups>
<Group refid='KBObjectGrp' package='98121D96-A7D8-468b-9310-B1F468F812AE'>
<Command refid='MyCommand' />
</Group>
</Groups>
Then in order to make your command available only to the objects you said before, you have to code a query handler for the command, that will rule when the command is enabled, disabled, or not visible at all. You can do that in the Initialize method of your package class.
public override void Initialize(IGxServiceProvider services)
{
base.Initialize(services);
CommandKey myCmdKey = new CommandKey(Id, "MyCommand");
AddCommand(myCmdKey, ExecMyCommand, QueryMyCommand);
}
private bool QueryMyCommand(CommandData data, ref CommandStatus status)
{
var selection = KBObjectSelectionHelper.TryGetKBObjectsFrom(data.Context).ToList();
status.Visible(selection.Count > 0 && selection.All(obj => obj.Type == ObjClass.Transaction || obj.Type == ObjClass.WebPanel));
return true;
}
private bool ExecMyCommand(CommandData data)
{
// Your command here
return true;
}
I'm using some helper classes here in order to get the objects from the selection, and then a class named ObjClass which exposes the guid of the most common object types. If you feel something isn't clear enough, don't hesitate to reach out.
Decompiling the Genexus dll and looking for the resource called package, you can infer what the names are.
It's cumbersome but it works

programatically adding an on-tap attribute referencing a dart function for a HtmlElement

I have a dart function:
_addSelection(HtmlElement ele){
ele.classes.add("selection");
}
I would either want 1 or 2 things to occur, either A) execute an on-tap and on-track function given the selection class.... OR Dynamically add the on-tap and on-track attributes referencing reflected dart functions.
I have 2 functions:
#reflectable
onTap(CustomEventWrapper cew, params){
//...
}
#reflectable
onTrack(CustomEventWrapper cew, params){
//...
}
I was looking at the HtmlElement class and documentation and I wasnt quite understanding how to do this.
Edit if I were using jQuery and Javascript, I would be doing something as simple as:
$(document).on("tap", function(){});
$(document).on("track", function(){});
Edit2 Added Angular Dart because both designs leverage Dart backend and markup front end.
You could do:
_addSelection(HtmlElement ele) {
ele.classes.add("selection");
ele.onTouchEnd.listen((TouchEvent touch) {
...
});
}
That would give you something close to the tap event. If you wanted to get really fancy you could also listen for onTouchStart and only call your onTap handler when the time between the start and end is small.

How can I call a function in a template based on a component?

This is part of my template:
<!-- This is the one I want! -->
<label>{{l10n('hallo') | translate}}</label>
If my Component has a function l10n its no problem to call the l10n-function
<label>{{cmp.l10n('hallo') | translate}}</label>
But that's not what I want - if possible I want l10n(<string>), somehow a global function for this template...
In AngularJS to achieve something linke this they add a function to the Controller-Scope: https://stackoverflow.com/a/12466994/504184
My problem here is that I don't have a Controller - I'm in a Component...
Second thing is that the Scope in AngularDart is quite different compared to the Scope in AngularJS...
You can inject the Scope in your Component and add the function.
#Component(selector: 'my-comp')
class Comp {
Comp(Scope scope) {
scope.context['l10n'] = (str) => "Boo[$str]";
}
}
However, we are thinking about removing this feature in an upcoming version of AngularDart.
James answer was right before Angular 1.0 - now its even simpler.
class MyComponent {
...
L10N tr(final String text) {
return new L10N(text);
}
}
<label class="medium">{{tr('Projectname:') | translate}}</label>
Thats it!

Provide callback for custom component

I made a custom component which basically wraps a d3 line chart. Now I want to be able to register a callback for clicks on the lines in the chart.
I gave the component a #NgCallback parameter, which I then send events to:
class NetworkSummaryComponent implements NgShadowRootAware {
#NgCallback('callback')
Function callback;
void onShadowRoot(ShadowRoot shadowRoot) {
...
chart.callMethod('listen', ['line-click', (ev) {
var name = ev.callMethod('getLineName');
print(name);
callback({'name': name});
}]);
}
}
When using the component, I specify a function of my controller as callback:
<network-summary
...
callback="ctrl.lineClicked">
</network-summary>
However, that function is never actually called, put I know the callback arrives from the JS side because the print in the first snippet is executed.
If I instead specify the attribute as callback="ctrl.lineClicked()" I get a strange exception:
Closure call with mismatched arguments: function 'call'
I could not find any official documentation on how to properly do callbacks, so I'm not exactly sure what I'm doing wrong.. Any ideas?
It turns out that I had to explicitly name the expected arguments in the attributes:
<network-summary
...
callback="ctrl.lineClicked(name)">
</network-summary>
Hope this is useful to the next person having this problem.

Under Rails3.1.1/Coffeescript - not always getting the function safety wrapper

I have recently started using coffeescript with Rails and I am finding that sometimes the generated javascript does not get the function safety wrapper.
Here is a sample project demonstrating it.
For example, this CS code, in index.js.coffee:
class Foo
afunc: ->
alert("afunc")
Correctly becomes:
(function() {
var Foo;
Foo = (function() {
function Foo() {}
Foo.prototype.afunc = function() {
return alert("afunc");
};
return Foo;
})();
}).call(this);
But this code, from other.js.coffee:
class App.Func
ouch: ->
alert("ouch")
becomes this un-wrapped version
App.Func = (function() {
function Func() {}
Func.prototype.ouch = function() {
return alert("ouch");
};
return Func;
})();
It seems to be due to the "App." prefix - which I can see affects naming/scope - but why is coffeescript compiling it differently...
App is defined in setup.js.coffee, like this:
window.App =
Models: {}
Which also does not get wrapped, unless I add a class into that file too.
I am sure it must be my misunderstanding - so thanks in advance for the pointers to the manual :).
EDIT:
I created this question as I thought it might be behind some issues I was having with my backbone/coffeescript app, but it seems that it was not. As the class is linked to a public/global thing "App", it seems to work wrapped or not. Still would be useful to know why its happening - is it by design?
The "function safety wrapper" feature you are using works to prevent local variables from being set on the global namespace. Since setting an object property (App.Func) doesn't affect the global namespace, the declaration is not wrapped in a function.

Resources