Is it possible to pass data into UI extensions assignments (meaning UI Extension X assigned to Field Y), in order to alter their functionality slightly for different situations, without having to reimplement the entire extension?
For example, CodeMirror is a really neat embedded editor, but it has a bunch of "modes," depending on what language you're working with. If we could even pass in a string to represent the desired mode when the extension is assigned to a field, that would remove the need to do a different extension just to use different syntax highlighting.
With this, there could now be a generic "CodeMirror Editor" UI extension which is then just configured a runtime.
On the other end of the extreme, we could specify entire JSON objects when the extension is assigned to a field, to further specify configuration options.
This would make UI extensions so much more...useful. Does this functionality exist now, or is there some way to reasonably make it work? Is there some place on the field specification where I can "park" a JSON string, then access it from inside the extension?
Contentful has launched something called "Configuration parameters" for UI extensions that could be used to solve this issue.
They have two types of parameters, installation and instance parameters. Installation parameters are set when installing the UI extension, and instance parameters are set when configuring a field on a content type to use the extension. The latter would be perfect for your use case.
To use this feature you need to:
Create a parameter definition for the UI extension in the extension.json file. E.g. a new instance parameter called "codeMirrorSettings" of type Symbol with name "CodeMirror Settings".
Within the extension, fetch the current parameters using extensionsApi.parameters.instance.codeMirrorSettings.
Documentation for configuration parameters can be found in Contentful's docs:
https://www.contentful.com/developers/docs/references/content-management-api/#/reference/ui-extensions/configuration-parameters
https://github.com/contentful/ui-extensions-sdk/blob/master/docs/ui-extensions-sdk-frontend.md#extensionparameters
What you could do is just read this setting from another field, be that a string or a json object.
For example the slug generator automatically generates its value from the title field.
You could perhaps do something like this:
const cfExt = window.contentfulExtension || window.contentfulWidget
cfExt.init(api => {
var langField = api.entry.fields.mirrorLang || 'default'
//Rest of implementation
})
Well, I wrote something for this, specific to my situation, but generalizable to others. This is an example if a UI extension that retrieves settings from another entry in the space, and uses it to dynamically configure itself.
https://github.com/deanebarker/contentful-code-editor
Related
I do not know that the question is right? Please do not take it your mind if it is crazy. Actually I am working on xpages application. There I need to do two things, that I want to add the picklist functionality and binding the dynamic data like field_1,field_2,field_3, ... upto n depands on customer choice.I am using the composite data for both custom controls. I can remove the picklist control's composite data and also I can do it by passing the scope variables. But that takes more time than the composite data.
I did not get any error. But the binded documents is not saving.
Is it possible to import the CCs that are having composite Data?
Code for first CC:-
<xc:viewpicklist datasrc="view1" dialogID="dialog1" dialogWidth="700px" dialogTitle="Pick this field value!!!">
<xc:this.viewColumn>
<xp:value>0</xp:value>
<xp:value>1</xp:value>
<xp:value>2</xp:value>
</xc:this.viewColumn>
</xc:viewpicklist>
Code for Second CC:-
<xc:BOM_Partinfo BOM_Partinfo="#{document1}"
TNUM="field#{index+1}" Desc="Desc#{index+1}" quan="Ea#{index+1}"
exp="exp#{index+1}" cap="cap#{index+1}" total="price#{index+1}"
RD="RD#{index+1}" m="manufact#{index+1}"
m_n="manufactnum#{index+1}">
</xc:BOM_Partinfo>
You can read information that is set in the properties of a custom control if it was static in the calling page:
var x = getComponent("yourcomponentid");
x.getPropertyMap().get("parametername");
but you want to propagate a data source from the outer control to the inner control...
You need to plan carefully. If you hand over the data source, then your custom control is dependent on a fixed set of fields in the data source (that would be a parameter of type com.ibm.xsp.model.DocumentDataSource). This would violate the encapsulation principles. So I would recommend you actually hand over data bindings - the advantage: you are very flexible what to bind to (not only data sources, but also beans and scope variables would work then). The trick is you provide the binding name as you would statically type it in (e.g. "document1.subject" or "requestScope.bla" ). In your control you then do
${"#{compositeData.field1}"}
${"#{compositeData.field2}"}
You need one for each field.
You cannot send a document data source to a custom control using composite data parameters.
You can try and use this script instead
http://openntf.org/XSnippets.nsf/snippet.xsp?id=access-datasources-of-custom-controls
Define data source in XP/CC where you want those CCs. Define parameter "dataSourceName" for both CCs. Inside each of them use EL "requestScope[compositeData.dataSourceName].fieldName" everywhere you want to bind to datasource.
I've found filter_var to be extremely useful in validating and sanitizing user input with PHP, but I've yet to find anything even remotely as convenient in ColdFusion (more specifically, CF8).
Obviously I can hack together something using REReplace, but that would take significantly more time to code up and would be much uglier than using the pre-defined filters available in PHP. Is there a more efficient way or do I just need to bite the bullet?
There are three different options available to you. Since you're attempting to manage user input, I assume you're using forms. isValid most closely mimics your functionality, allowing you to check if a value specified matches either a data type or a regular expression and returns true or false, and includes attributes by default to define a range. It does not support the ability to create a custom 'filter' beyond defining a regular expression however.
The second option would be using cfparam tags on your POST processing page, which allows you to specify the existance of a variable, test against a data type or define a regular expression, and optionally assign a default value if the variable doesn't exist. If you attempt to process a page where the field is not defined and no default value is assigned however, ColdFusion throws an error.
Finally, you can do validation by using cfform and cfinput fields on your form itself; which allows for client-side data validation for existence and types (it also supports server-side validation but it's implementation is sloppy), regular expressions, and input masking: taking user-inputted data and conforming it to a specific format (like adding dashes to phone numbers and zip codes).
I have been making good use of custom properties withing custom controls. Is there such thing as custom methods? Say I want something to happen in a CC. A good example is the show method of the dialog box extension. If I have a cc with a extension dialog inside, I want my custom control to have a Show method which insulates the end user programmer from the extension pages Shoe method.
Is there anyway to do this?
At runtime, all Custom Control elements become instances of the UIIncludeComposite class; as such, there are many built in methods that you can call against any given control instance, but there is no way to specify custom methods, as opposed to custom properties.
There are, however, at least two ways you could achieve the result you're after:
Convert your Custom Control to a component (this NotesIn9 episode describes the simplest approach to this process). Once you've migrated the class that Designer generated to one that won't get overridden every time you build your NSF, you can add custom methods without fear that the next build will just wipe them out again. Since Custom Controls are essentially just IBM's implementation of the JSF 2.0 notion of "composite components", you could also create a component from scratch that has the same behavior as your existing Custom Control but also supports custom behavior. Note that either approach does not necessarily require that you create an OSGi library... you can define these components directly in an NSF; you only need to push them to a library if you want to reuse them across multiple NSFs without having to copy the various files to each.
In the custom properties for your control, include one property that accepts an API object. In other words, you could create any object (say, a Java class or SSJS object) that supports the custom methods you wish to define, and pass that object to the control. You could then call those methods by getting a handle on the object via the CC's property map.
For example:
<myCC id="myCustomControl" API="#{someObject}" />
Assuming whatever #{someObject} resolves to includes a show() method, you can call that method by getting a handle on the instance that has been passed to the control:
var cc = getComponent("myCustomControl");
var ccProperties = cc.getPropertyMap();
var ccAPI = ccProperties.get("API");
ccAPI.show(cc);
In the above example, I'm passing the actual Custom Control to the show() method, because the object itself isn't aware of the Custom Control it was passed to. So if that method needs to get a handle on its children to toggle their rendered property, for example, then it needs some other way of determining its context.
Tim's solution with passing in the object is a great solution to that.
Just something that popped into my head, would be easy to make a property similar to the rendered property on a control. Pass in a value and inside the custom control do something based on its value ie. if true display dialog, else hide, in the XPage during run time modify this value and partial refresh the control, the logic will be re run by this and the control will display etc.
Another solution could be to include a JavaScript library in your custom control providing functions (your custom control methods) where you'd have to pass in the id of the custom control instance.
When beginning to develop against SharePoint I did not fully understand all the ins and outs initially. I created a list definition (for a document library) and associated various custom actions to it. Unfortunately, I used the following for the list definition itself:
<ListTemplate...
...
Type="101"
...
And to register the CustomActions against the list:
<CustomAction...
...
RegistrationType="List"
RegistrationId="101"
...
Of course, this means that the custom actions are visible for all document libraries where the feature is activated which is undesirable behaviour. Also, there are lots of these document libraries that have been created from the above list definition in production.
What is the best way to fix this problem? My assumption is that I somehow need to change the "Type" attribute of the already existing lists, but I do not know how to do that. Can it be done via some direct SQL manipulation perhaps? Or is there a better way?
Note: I can see that the AllLists table has a column tp_ServerTemplate, is that the right thing to change?
Modifying the SharePoint database is completely unsupported by Microsoft. Please do not do this on production!
Another option is to create a content type and associate the custom action with that. You may need to write a simple console application to iterate through your existing document libraries and add the content type so it is available for use. The existing documents that you'd like the custom action to apply to would need their content types changed as well.
From some quick initial testing it does look like changing the AllLists table does the trick.
So steps to resolve:
1) Change List Definition Type attribute to be a unique value (for example 11000)
2) Change the CustomAction RegistrationId attributes to be the same (11000)
3) Update the tp_servertemplate column in the AllLists table to be the new template Type (11000) for all the relevant lists.
In my DSL project I have a shape with a number of decorators that are linked to properties on my domain class. But even though ieach decorator has a DisplayName property (set to a meaningfull value) it does not appear in the generated DSL project. (I have not forgtten to use regenerate the t4 files.)
Do I have to create another decorator for each property that only has the display name as a value that I wish to display or is there some other way that I can't figure out right now?
I assume by a display name for the decorator you mean you want the element in the generated DSL to appear as "Example = a_value" where a_value is the actual value and Example is the property name.
What I've done with this in the past is to create second property "ExampleDisplay" that's not browsable and is what the decorator actually points to. I then set the Kind property of the ExampleDisplay to "Calculated". You then need to provide the method that the toolkit tries to call to display the decorator which you can do a partial class.
partial class ExampleElement
{
string GetExampleDisplayValue()
{
return "Example : " + this.Example;
}
}
This is not ideal as you don't get a good way of setting the property on the DSL diagram you have to use the properties window. (There's sometime lags from the property window unless you hook into the update of the underlying property too). Getting the slick editing in the GUI that actual DSL toolkit does maybe possible but I haven't found out how.
It maybe worth ask VSX forums if you haven't already done so.