@@ -105,6 +105,26 @@ function $InterpolateProvider() {
105
105
* expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
106
106
* ```
107
107
*
108
+ * The function returned by `$interpolate` takes an optional second argument, `allOrNothing`.
109
+ * If `allOrNothing` is `true`, the interpolation function will return `undefined` unless all
110
+ * embedded expressions within the text are defined.
111
+ *
112
+ * ```js
113
+ * var $interpolate = ...; // injected
114
+ * var exp = $interpolate('{{greeting}} {{name}}!');
115
+ * var context = {greeting: 'Hey', name: undefined };
116
+ *
117
+ * // default "forgiving" mode
118
+ * expect(exp(context).toEqual('Hello !');
119
+ *
120
+ * // "allOrNothing" mode
121
+ * expect(exp(context, true).toBeUndefined();
122
+ * context.name = 'Angular';
123
+ * expect(exp(context, true).toEqual('Hello Angular!');
124
+ * ```
125
+ *
126
+ * `allOrNothing` is useful for interpolating URLs. `ngHref`, `ngSrc`, and `ngSrcset` use this
127
+ * behavior.
108
128
*
109
129
* @param {string } text The text with markup to interpolate.
110
130
* @param {boolean= } mustHaveExpression if set to true then the interpolation string must have
@@ -114,10 +134,11 @@ function $InterpolateProvider() {
114
134
* result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
115
135
* trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
116
136
* provides Strict Contextual Escaping for details.
117
- * @returns {function(context) } an interpolation function which is used to compute the
137
+ * @returns {function(context, allOrNothing ) } an interpolation function which is used to compute the
118
138
* interpolated string. The function has these parameters:
119
139
*
120
140
* - `context`: evaluation context for all expressions embedded in the interpolated text
141
+ * - `allOrNothing`: if `true`, the undefined unless all embedded expressions are defined
121
142
*/
122
143
function $interpolate ( text , mustHaveExpression , trustedContext ) {
123
144
var startIndex ,
@@ -182,23 +203,29 @@ function $InterpolateProvider() {
182
203
return concat . join ( '' ) ;
183
204
} ;
184
205
185
- var stringify = function ( value ) {
206
+ var getValue = function ( value ) {
186
207
if ( trustedContext ) {
187
208
value = $sce . getTrusted ( trustedContext , value ) ;
188
209
} else {
189
210
value = $sce . valueOf ( value ) ;
190
211
}
191
212
192
- if ( value === null || isUndefined ( value ) ) {
213
+ return value ;
214
+ } ;
215
+
216
+ var stringify = function ( value ) {
217
+ if ( isUndefined ( value ) || value === null ) {
193
218
value = '' ;
194
- } else if ( typeof value != 'string' ) {
219
+ }
220
+ if ( typeof value != 'string' ) {
195
221
value = toJson ( value ) ;
196
222
}
197
223
198
224
return value ;
199
225
} ;
200
226
201
- return extend ( function interpolationFn ( context ) {
227
+ return extend ( function interpolationFn ( context , allOrNothing ) {
228
+ allOrNothing = ! ! allOrNothing ;
202
229
var scopeId = context . $id || 'notAScope' ;
203
230
var lastValues = lastValuesCache . values [ scopeId ] ;
204
231
var lastResult = lastValuesCache . results [ scopeId ] ;
@@ -225,7 +252,11 @@ function $InterpolateProvider() {
225
252
226
253
try {
227
254
for ( ; i < ii ; i ++ ) {
228
- val = stringify ( parseFns [ i ] ( context ) ) ;
255
+ val = getValue ( parseFns [ i ] ( context ) ) ;
256
+ if ( allOrNothing && isUndefined ( val ) ) {
257
+ return ;
258
+ }
259
+ val = stringify ( val ) ;
229
260
if ( val !== lastValues [ i ] ) {
230
261
inputsChanged = true ;
231
262
}
0 commit comments