1
+ <!doctype html>
2
+ < html ng-app ="Demo ">
3
+ < head >
4
+ < meta charset ="utf-8 " />
5
+
6
+ < title >
7
+ Using URL Interpolation With $http In AngularJS
8
+ </ title >
9
+
10
+ </ head >
11
+ < body ng-controller ="DemoController ">
12
+
13
+ < h1 >
14
+ Using URL Interpolation With $http In AngularJS
15
+ </ h1 >
16
+
17
+
18
+ <!-- Initialize scripts. -->
19
+ < script type ="text/javascript " src ="../../vendor/jquery/jquery-2.1.0.min.js "> </ script >
20
+ < script type ="text/javascript " src ="../../vendor/angularjs/angular-1.2.16.min.js "> </ script >
21
+ < script type ="text/javascript ">
22
+
23
+ // Define the module for our AngularJS application.
24
+ var app = angular . module ( "Demo" , [ ] ) ;
25
+
26
+
27
+ // -------------------------------------------------- //
28
+ // -------------------------------------------------- //
29
+
30
+
31
+ // I control the main demo.
32
+ app . controller (
33
+ "DemoController" ,
34
+ function ( $scope , httpi ) {
35
+
36
+ // NOTE: The (.|.) notation will be stripped out automatically; it's only
37
+ // here to improve readability of the "happy paths" of labels. The
38
+ // following urls are identical:
39
+ // --
40
+ // api/friends/( :listCommand | :id/:itemCommand )
41
+ // api/friends/:listCommand:id/:itemCommand
42
+ var url = "api/friends/( :listCommand | :id/:itemCommand )" ;
43
+
44
+ console . warn ( "None of the API enpoints exist - they will all throw 404." ) ;
45
+
46
+ // Clear list of friends - matching listCommand.
47
+ httpi ( {
48
+ method : "post" ,
49
+ url : url ,
50
+ data : {
51
+ listCommand : "reset"
52
+ }
53
+ } ) ;
54
+
55
+ // Create a new friend - no matching URL parameters.
56
+ httpi ( {
57
+ method : "post" ,
58
+ url : url ,
59
+ data : {
60
+ name : "Tricia"
61
+ }
62
+ } ) ;
63
+
64
+ // Get a given friend - ID matching.
65
+ httpi ( {
66
+ method : "get" ,
67
+ url : url ,
68
+ data : {
69
+ id : 4
70
+ }
71
+ } ) ;
72
+
73
+ // Make best friend - ID, itemCommand matching.
74
+ httpi ( {
75
+ method : "post" ,
76
+ url : url ,
77
+ data : {
78
+ id : 4 ,
79
+ itemCommand : "make-best-friend"
80
+ }
81
+ } ) ;
82
+
83
+ // Get besties - no matching URL parameters.
84
+ httpi ( {
85
+ method : "get" ,
86
+ url : url ,
87
+ params : {
88
+ limit : "besties"
89
+ }
90
+ } ) ;
91
+
92
+ }
93
+ ) ;
94
+
95
+
96
+ // -------------------------------------------------- //
97
+ // -------------------------------------------------- //
98
+
99
+
100
+ // I provide a proxy for the $http service that interpolates the URL of the
101
+ // request before executing the underlying HTTP call.
102
+ // --
103
+ // NOTE: The "i" stands for "interpolation".
104
+ app . service (
105
+ "httpi" ,
106
+ function ( $http ) {
107
+
108
+ // Return the public API.
109
+ return ( httpProxy ) ;
110
+
111
+
112
+ // ---
113
+ // PUBLIC METHODS.
114
+ // ---
115
+
116
+
117
+ // I proxy the $http service and merge the params and data values into
118
+ // the URL before creating the underlying request.
119
+ function httpProxy ( config ) {
120
+
121
+ config . url = interpolateUrl ( config . url , config . params , config . data ) ;
122
+
123
+ return ( $http ( config ) ) ;
124
+
125
+ }
126
+
127
+
128
+ // ---
129
+ // PRIVATE METHODS.
130
+ // ---
131
+
132
+
133
+ // I move values from the params and data arguments into the URL where
134
+ // there is a match for labels. When the match occurs, the key-value
135
+ // pairs are removed from the parent object and merged into the string
136
+ // value of the URL.
137
+ function interpolateUrl ( url , params , data ) {
138
+
139
+ // Make sure we have an object to work with - makes the rest of the
140
+ // logic easier.
141
+ params = ( params || { } ) ;
142
+ data = ( data || { } ) ;
143
+
144
+ // Strip out the delimiter fluff that is only there for readability
145
+ // of the optional label paths.
146
+ url = url . replace ( / ( \( \s * | \s * \) | \s * \| \s * ) / g, "" ) ;
147
+
148
+ // Replace each label in the URL (ex, :userID).
149
+ url = url . replace (
150
+ / : ( [ a - z ] \w * ) / gi,
151
+ function ( $0 , label ) {
152
+
153
+ // NOTE: Giving "data" precedence over "params".
154
+ return ( popFirstKey ( data , params , label ) || "" ) ;
155
+
156
+ }
157
+ ) ;
158
+
159
+ // Strip out any repeating slashes (but NOT the http:// version).
160
+ url = url . replace ( / ( ^ | [ ^ : ] ) [ \/ ] { 2 , } / g, "$1/" ) ;
161
+
162
+ // Strip out any trailing slash.
163
+ url = url . replace ( / \/ + $ / i, "" ) ;
164
+
165
+ return ( url ) ;
166
+
167
+ }
168
+
169
+
170
+ // I take 1..N objects and a key and perform a popKey() action on the
171
+ // first object that contains the given key. If other objects in the list
172
+ // also have the key, they are ignored.
173
+ function popFirstKey ( object1 , object2 , objectN , key ) {
174
+
175
+ // Convert the arguments list into a true array so we can easily
176
+ // pluck values from either end.
177
+ var objects = Array . prototype . slice . call ( arguments ) ;
178
+
179
+ // The key will always be the last item in the argument collection.
180
+ var key = objects . pop ( ) ;
181
+
182
+ var object = null ;
183
+
184
+ // Iterate over the arguments, looking for the first object that
185
+ // contains a reference to the given key.
186
+ while ( object = objects . shift ( ) ) {
187
+
188
+ if ( object . hasOwnProperty ( key ) ) {
189
+
190
+ return ( popKey ( object , key ) ) ;
191
+
192
+ }
193
+
194
+ }
195
+
196
+ }
197
+
198
+
199
+ // I delete the key from the given object and return the value.
200
+ function popKey ( object , key ) {
201
+
202
+ var value = object [ key ] ;
203
+
204
+ delete ( object [ key ] ) ;
205
+
206
+ return ( value ) ;
207
+
208
+ }
209
+
210
+ }
211
+ ) ;
212
+
213
+ </ script >
214
+
215
+ </ body >
216
+ </ html >
0 commit comments