Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit a02ed88

Browse files
committed
docs($compile): add docs for ngProp and ngOn bindings
The docs are written as if ngProp and ngOn were regular directives, which makes them easier to find. Closes #16627
1 parent a5914c9 commit a02ed88

File tree

2 files changed

+320
-1
lines changed

2 files changed

+320
-1
lines changed

src/ng/compile.js

+319
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,325 @@
10441044
*
10451045
*/
10461046

1047+
/**
1048+
* @ngdoc directive
1049+
* @name ngProp
1050+
* @restrict A
1051+
* @element ANY
1052+
*
1053+
* @usage
1054+
*
1055+
* ```html
1056+
* <ANY ng-prop-propname="expression">
1057+
* </ANY>
1058+
* ```
1059+
*
1060+
* or with uppercase letters in property (e.g. "propName"):
1061+
*
1062+
*
1063+
* ```html
1064+
* <ANY ng-prop-prop_name="expression">
1065+
* </ANY>
1066+
* ```
1067+
*
1068+
*
1069+
* @description
1070+
* The `ngProp` directive binds an expression to a DOM element property.
1071+
* `ngProp` allows writing to arbitrary properties by including
1072+
* the property name in the attribute, e.g. `ng-prop-value="'my value'"` binds 'my value' to
1073+
* the `value` property.
1074+
*
1075+
* Usually, it's not necessary to write to properties in AngularJS, as the built-in directives
1076+
* handle the most common use cases (instead of the above example, you would use {@link ngValue}).
1077+
*
1078+
* However, [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements)
1079+
* often use custom properties to hold data, and `ngProp` can be used to provide input to these
1080+
* custom elements.
1081+
*
1082+
* ## Binding to camelCase properties
1083+
*
1084+
* Since HTML attributes are case-insensitive, camelCase properties like `innerHTML` must be escaped.
1085+
* AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so
1086+
* `innerHTML` must be written as `ng-prop-inner_h_t_m_l="expression"` (Note that this is just an
1087+
* example, and for binding HTML {@link ngBindHtml} should be used.
1088+
*
1089+
* ## Security
1090+
*
1091+
* Binding expressions to arbitrary properties poses a security risk, as properties like `innerHTML`
1092+
* can insert potentially dangerous HTML into the application, e.g. script tags that execute
1093+
* malicious code.
1094+
* For this reason, `ngProp` applies Strict Contextual Escaping with the {@link ng.$sce $sce service}.
1095+
* This means vulnerable properties require their content to be "trusted", based on the
1096+
* context of the property. For example, the `innerHTML` is in the `HTML` context, and the
1097+
* `iframe.src` property is in the `RESOURCE_URL` context, which requires that values written to
1098+
* this property are trusted as a `RESOURCE_URL`.
1099+
*
1100+
* This can be set explicitly by calling $sce.trustAs(type, value) on the value that is
1101+
* trusted before passing it to the `ng-prop-*` directive. There are exist shorthand methods for
1102+
* each context type in the form of {@link ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl()} et al.
1103+
*
1104+
* In some cases you can also rely upon automatic sanitization of untrusted values - see below.
1105+
*
1106+
* Based on the context, other options may exist to mark a value as trusted / configure the behavior
1107+
* of {@link ng.$sce}. For example, to restrict the `RESOURCE_URL` context to specific origins, use
1108+
* the {@link $sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist()}
1109+
* and {@link $sceDelegateProvider#resourceUrlBlacklist resourceUrlBlacklist()}.
1110+
*
1111+
* {@link ng.$sce#what-trusted-context-types-are-supported- Find out more about the different context types}.
1112+
*
1113+
* ### HTML Sanitization
1114+
*
1115+
* By default, `$sce` will throw an error if it detects untrusted HTML content, and will not bind the
1116+
* content.
1117+
* However, if you include the {@link ngSanitize ngSanitize module}, it will try to sanitize the
1118+
* potentially dangerous HTML, e.g. strip non-whitelisted tags and attributes when binding to
1119+
* `innerHTML`.
1120+
*
1121+
* @example
1122+
* ### Binding to different contexts
1123+
*
1124+
* <example name="ngProp" module="exampleNgProp">
1125+
* <file name="app.js">
1126+
* angular.module('exampleNgProp', [])
1127+
* .component('main', {
1128+
* templateUrl: 'main.html',
1129+
* controller: function($sce) {
1130+
* this.safeContent = '<strong>Safe content</strong>';
1131+
* this.unsafeContent = '<button onclick="alert(\'Hello XSS!\')">Click for XSS</button>';
1132+
* this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent);
1133+
* }
1134+
* });
1135+
* </file>
1136+
* <file name="main.html">
1137+
* <div>
1138+
* <div class="prop-unit">
1139+
* Binding to a property without security context:
1140+
* <div class="prop-binding" ng-prop-inner_text="$ctrl.safeContent"></div>
1141+
* <span class="prop-note">innerText</span> (safeContent)
1142+
* </div>
1143+
*
1144+
* <div class="prop-unit">
1145+
* "Safe" content that requires a security context will throw because the contents could potentially be dangerous ...
1146+
* <div class="prop-binding" ng-prop-inner_h_t_m_l="$ctrl.safeContent"></div>
1147+
* <span class="prop-note">innerHTML</span> (safeContent)
1148+
* </div>
1149+
*
1150+
* <div class="prop-unit">
1151+
* ... so that actually dangerous content cannot be executed:
1152+
* <div class="prop-binding" ng-prop-inner_h_t_m_l="$ctrl.unsafeContent"></div>
1153+
* <span class="prop-note">innerHTML</span> (unsafeContent)
1154+
* </div>
1155+
*
1156+
* <div class="prop-unit">
1157+
* ... but unsafe Content that has been trusted explicitly works - only do this if you are 100% sure!
1158+
* <div class="prop-binding" ng-prop-inner_h_t_m_l="$ctrl.trustedUnsafeContent"></div>
1159+
* <span class="prop-note">innerHTML</span> (trustedUnsafeContent)
1160+
* </div>
1161+
* </div>
1162+
* </file>
1163+
* <file name="index.html">
1164+
* <main></main>
1165+
* </file>
1166+
* <file name="styles.css">
1167+
* .prop-unit {
1168+
* margin-bottom: 10px;
1169+
* }
1170+
*
1171+
* .prop-binding {
1172+
* min-height: 30px;
1173+
* border: 1px solid blue;
1174+
* }
1175+
*
1176+
* .prop-note {
1177+
* font-family: Monospace;
1178+
* }
1179+
* </file>
1180+
* </example>
1181+
*
1182+
*
1183+
* @example
1184+
* ### Binding to innerHTML with ngSanitize
1185+
*
1186+
* <example name="ngProp" module="exampleNgProp" deps="angular-sanitize.js">
1187+
* <file name="app.js">
1188+
* angular.module('exampleNgProp', ['ngSanitize'])
1189+
* .component('main', {
1190+
* templateUrl: 'main.html',
1191+
* controller: function($sce) {
1192+
* this.safeContent = '<strong>Safe content</strong>';
1193+
* this.unsafeContent = '<button onclick="alert(\'Hello XSS!\')">Click for XSS</button>';
1194+
* this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent);
1195+
* }
1196+
* });
1197+
* </file>
1198+
* <file name="main.html">
1199+
* <div>
1200+
* <div class="prop-unit">
1201+
* "Safe" content will be sanitized ...
1202+
* <div class="prop-binding" ng-prop-inner_h_t_m_l="$ctrl.safeContent"></div>
1203+
* <span class="prop-note">innerHTML</span> (safeContent)
1204+
* </div>
1205+
*
1206+
* <div class="prop-unit">
1207+
* ... as will dangerous content:
1208+
* <div class="prop-binding" ng-prop-inner_h_t_m_l="$ctrl.unsafeContent"></div>
1209+
* <span class="prop-note">innerHTML</span> (unsafeContent)
1210+
* </div>
1211+
*
1212+
* <div class="prop-unit">
1213+
* ... and content that has been trusted explicitly works the same as without ngSanitize:
1214+
* <div class="prop-binding" ng-prop-inner_h_t_m_l="$ctrl.trustedUnsafeContent"></div>
1215+
* <span class="prop-note">innerHTML</span> (trustedUnsafeContent)
1216+
* </div>
1217+
* </div>
1218+
* </file>
1219+
* <file name="index.html">
1220+
* <main></main>
1221+
* </file>
1222+
* <file name="styles.css">
1223+
* .prop-unit {
1224+
* margin-bottom: 10px;
1225+
* }
1226+
*
1227+
* .prop-binding {
1228+
* min-height: 30px;
1229+
* border: 1px solid blue;
1230+
* }
1231+
*
1232+
* .prop-note {
1233+
* font-family: Monospace;
1234+
* }
1235+
* </file>
1236+
* </example>
1237+
*
1238+
*/
1239+
1240+
/** @ngdoc directive
1241+
* @name ngOn
1242+
* @restrict A
1243+
* @element ANY
1244+
*
1245+
* @usage
1246+
*
1247+
* ```html
1248+
* <ANY ng-on-eventname="expression">
1249+
* </ANY>
1250+
* ```
1251+
*
1252+
* or with uppercase letters in property (e.g. "eventName"):
1253+
*
1254+
*
1255+
* ```html
1256+
* <ANY ng-on-event_name="expression">
1257+
* </ANY>
1258+
* ```
1259+
*
1260+
* @description
1261+
* The `ngOn` directive adds an event listener to a DOM element via
1262+
* {@link angular.element angular.element().on()}, and evaluates an expression when the event is
1263+
* fired.
1264+
* `ngOn` allows adding listeners for arbitrary events by including
1265+
* the event name in the attribute, e.g. `ng-on-drop="onDrop()"` executes the 'onDrop()' expression
1266+
* when the `drop` event is fired.
1267+
*
1268+
* AngularJS provides specific directives for many events, such as {@link ngClick}, so in most
1269+
* cases it is not necessary to use `ngOn`. However, AngularJS does not support all events
1270+
* (e.g. the `drop` event in the example above), and new events might be introduced in later DOM
1271+
* standards.
1272+
*
1273+
* Another use-case for `ngOn` is listening to
1274+
* [custom events](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events)
1275+
* fired by
1276+
* [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements).
1277+
*
1278+
* ## Binding to camelCase properties
1279+
*
1280+
* Since HTML attributes are case-insensitive, camelCase properties like `myEvent` must be escaped.
1281+
* AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so
1282+
* `myEvent` must be written as `ng-on-my_event="expression"`.
1283+
*
1284+
* @example
1285+
* ### Bind to built-in DOM events
1286+
*
1287+
* <example name="ngOn" module="exampleNgOn">
1288+
* <file name="app.js">
1289+
* angular.module('exampleNgOn', [])
1290+
* .component('main', {
1291+
* templateUrl: 'main.html',
1292+
* controller: function() {
1293+
* this.clickCount = 0;
1294+
* this.mouseoverCount = 0;
1295+
*
1296+
* this.loadingState = 0;
1297+
* }
1298+
* });
1299+
* </file>
1300+
* <file name="main.html">
1301+
* <div>
1302+
* This is equivalent to `ngClick` and `ngMouseover`:<br>
1303+
* <button
1304+
* ng-on-click="$ctrl.clickCount = $ctrl.clickCount + 1"
1305+
* ng-on-mouseover="$ctrl.mouseoverCount = $ctrl.mouseoverCount + 1">Click or mouseover</button><br>
1306+
* clickCount: {{$ctrl.clickCount}}<br>
1307+
* mouseover: {{$ctrl.mouseoverCount}}
1308+
*
1309+
* <hr>
1310+
*
1311+
* For the `error` and `load` event on images no built-in AngularJS directives exist:<br>
1312+
* <img src="thisimagedoesnotexist.png" ng-on-error="$ctrl.loadingState = -1" ng-on-load="$ctrl.loadingState = 1"><br>
1313+
* <div ng-switch="$ctrl.loadingState">
1314+
* <span ng-switch-when="0">Image is loading</span>
1315+
* <span ng-switch-when="-1">Image load error</span>
1316+
* <span ng-switch-when="1">Image loaded successfully</span>
1317+
* </div>
1318+
* </div>
1319+
* </file>
1320+
* <file name="index.html">
1321+
* <main></main>
1322+
* </file>
1323+
* </example>
1324+
*
1325+
*
1326+
* @example
1327+
* ### Bind to custom DOM events
1328+
*
1329+
* <example name="ngOnCustom" module="exampleNgOn">
1330+
* <file name="app.js">
1331+
* angular.module('exampleNgOn', [])
1332+
* .component('main', {
1333+
* templateUrl: 'main.html',
1334+
* controller: function() {
1335+
* this.eventLog = '';
1336+
*
1337+
* this.listener = function($event) {
1338+
* this.eventLog = 'Event with type "' + $event.type + '" fired at ' + $event.detail;
1339+
* };
1340+
* }
1341+
* })
1342+
* .component('childComponent', {
1343+
* templateUrl: 'child.html',
1344+
* controller: function($element) {
1345+
* this.fireEvent = function() {
1346+
* var event = new CustomEvent('customtype', { detail: new Date()});
1347+
*
1348+
* $element[0].dispatchEvent(event);
1349+
* };
1350+
* }
1351+
* });
1352+
* </file>
1353+
* <file name="main.html">
1354+
* <child-component ng-on-customtype="$ctrl.listener($event)"></child-component><br>
1355+
* <span>Event log: {{$ctrl.eventLog}}</span>
1356+
* </file>
1357+
* <file name="child.html">
1358+
<button ng-click="$ctrl.fireEvent()">Fire custom event</button>
1359+
* </file>
1360+
* <file name="index.html">
1361+
* <main></main>
1362+
* </file>
1363+
* </example>
1364+
*/
1365+
10471366
var $compileMinErr = minErr('$compile');
10481367

10491368
function UNINITIALIZED_VALUE() {}

src/ng/sce.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ function $SceDelegateProvider() {
623623
* | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
624624
* | `$sce.MEDIA_URL` | For URLs that are safe to render as media. Is automatically converted from string by sanitizing when needed. |
625625
* | `$sce.URL` | For URLs that are safe to follow as links. Is automatically converted from string by sanitizing when needed. Note that `$sce.URL` makes a stronger statement about the URL than `$sce.MEDIA_URL` does and therefore contexts requiring values trusted for `$sce.URL` can be used anywhere that values trusted for `$sce.MEDIA_URL` are required.|
626-
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` or `$sce.MEDIA_URL` do and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` or `$sce.MEDIA_URL` are required. |
626+
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` or `$sce.MEDIA_URL` do and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` or `$sce.MEDIA_URL` are required. <br><br> The {@link $sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider#resourceUrlWhitelist()} and {@link $sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider#resourceUrlBlacklist()} can be used to restrict trusted origins for `RESOURCE_URL` |
627627
* | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
628628
*
629629
*

0 commit comments

Comments
 (0)