Skip to content

Commit

Permalink
Added ww-appConfig and related documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian mccullough authored and Brian mccullough committed Dec 13, 2016
1 parent 151fa58 commit 67b42a3
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 1 deletion.
55 changes: 55 additions & 0 deletions Documentation/IntroducingWidgetWrangler.md
Expand Up @@ -53,6 +53,7 @@ So the answer to the question, "Why should I care?" is because widgets give you:

* **Flexibility:** Widgets can be versioned independently and moved around freely on web pages in and out of SharePoint
* **Reusability:** Widgets allow one code set to run in a web part, on a SharePoint form or page, or outside of SharePoint
* **Configurability:** Widgets can be configured such that the same code set can be used in slightly different ways across many different pages or multiple times within the same page
* **Maintainability:** Widgets written in an MV* framework like Angular or Knockout are easier to test and maintain

Any snippet of HTML with JavaScript can be considered a widget,
Expand Down Expand Up @@ -365,6 +366,60 @@ generates a unique index for each instance that's used in a button
click attribute. This index is passed into the click event handler to allow
it to find the correct instance when the event fires.

## Configuration

Angular widgets have supported configuration since version 1.0 by way of the *ng-init* directive (see the [weather example above](#angularjs-widgets)).

As of version 1.2, the Widget Wrangler framework now supports the ability to pass configuration data to other types of widgets as well. The *ww-appConfig* custom attribute can be used to pass any data (string, JSON, etc) you wish to any non-Angular wiget. This data is passed as an additional argument to the *ww-appBind* initialization method and can be validated and evaluated as your custom widget sees fit. See the [Widget Wrangler Reference](WidgetWranglerReference.md) for more details.

For example, assuming we have the following widget code:

var sampleWidgetWithConfig = sampleWidgetWithConfig || {};

sampleWidgetWithConfig.init = function(element, config) {
var configObj = null;
if (config) {
configObj = JSON.parse(config);
}
if (configObj && typeof(configObj.Name) == 'string' && typeof(configObj.LikesWidgetWrangler) == 'boolean') {
var output = configObj.LikesWidgetWrangler ? ' likes the widgets' : ' does not like widget wranger and must be crazy';
element.insertAdjacentHTML('beforeend', '<span>' + configObj.Name + ' ' + output + '</span>');
} else {
element.insertAdjacentHTML('beforeend', '<span>Sorry, bad config in this web part. Check the configuration and try again.</span>');
}
}

Several of these can be placed on the same page with different configurations:

<div>
<h2>Widget 1</h2>
<script type="text/javascript"
src="/Style Library/WebParts/js/pnp-ww.js"
ww-appname='SampleWidgetWithConfig'
ww-appbind='sampleWidgetWithConfig.init'
ww-appConfig='{"Name":"brian", "LikesWidgetWrangler":true}'
ww-appscripts='[{"src": "~/sampleWidgetWithConfig.js", "priority":0}]'>
</script>
</div>
<div>
<h2>Widget 2</h2>
<script type="text/javascript"
src="/Style Library/WebParts/js/pnp-ww.js"
ww-appname='SampleWidgetWithConfig'
ww-appbind='sampleWidgetWithConfig.init'
ww-appConfig='{"Name":"jim", "LikesWidgetWrangler":false}'
ww-appscripts='[{"src": "~/sampleWidgetWithConfig.js", "priority":0}]'>
</script>
</div>

![Configurable Widget](./images/ConfigurableWidget.png)
<br />
_Configurable Widget_


## Widgets in SharePoint

The Patterns and Practices library includes
Expand Down
1 change: 1 addition & 0 deletions Documentation/WidgetWranglerReference.md
Expand Up @@ -31,6 +31,7 @@ Tag | Required | Description
ww-appName | yes | Used to create a name for the app. In the case of an Angular widget, this is the module that will be passed to the angular.bootstrap function when starting the widget. If multiple Angular modules need to be booted, you can pass a collection of strings instead of a single string.
ww-appType | no | Currently "Angular" is the only supported framework that will auto-bind upon load completion.
ww-appBind | no | The function to be executed when all the script files have completed loading.
ww-appConfig | no | The additional data (string, JSON, etc) to be passed to the app-Bind method.
ww-appCss | no | A JSON object that defines the css files the widget needs in order to run
ww-appScripts | yes | A JSON object that defines the javascript files the widget needs in order to run

Expand Down
Binary file added Documentation/images/ConfigurableWidget.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion WWBase/WWBase/pnp-ww.js
Expand Up @@ -154,6 +154,7 @@ var ww = window.ww || function () {
appStatus: "Not Started", // App Status is "Not Started", "Waiting", "Complete" or "Error"
appScripts: [], // Array of appScriptObj objects for script this app requires
appCss: [], // Array of appCssObj objects for css files this app requires
appConfig: null, // Array of appCssObj objects for css files this app requires
appExecPriority: 0, // The app's current executing priorty.
appMaxPriority: 0, // The app's highest priority.
// startLoading()
Expand Down Expand Up @@ -253,7 +254,7 @@ var ww = window.ww || function () {
bindFn = bindFn[fnElements[i]];
}
if (typeof bindFn === 'function') {
bindFn(this.appElement);
bindFn(this.appElement, this.appConfig);
console.log(this.appName + "(" + this.appId + ")" + " with function: " + this.appBind + " loading complete.");
} else {
console.log("Error bootstrapping application: " + this.appName + "(" + this.appId + ") with function: " + this.appBind);
Expand Down Expand Up @@ -347,6 +348,8 @@ var ww = window.ww || function () {
} catch (e) {
console.log("Error parsing ww-appCss tag: " + e);
}
var appConfig = element.getAttribute("ww-appConfig");
if (appConfig === null) { appConfig = ""; }

if (appScripts !== null && appName.length > 0 && (appType.length > 0 || appBind.length > 0) && validAppType) {
// Create the app object
Expand All @@ -356,6 +359,7 @@ var ww = window.ww || function () {
newApp.appType = appType;
newApp.appBind = appBind;
newApp.appElement = elementToBind;
newApp.appConfig = appConfig;

// Add an appScript object for each script the app requires
for (var i = 0; i < appScripts.length; i++) {
Expand Down

0 comments on commit 67b42a3

Please sign in to comment.