{"id":1249,"date":"2012-12-17T22:11:45","date_gmt":"2012-12-18T05:11:45","guid":{"rendered":"http:\/\/thesmithfam.org\/blog\/?p=1249"},"modified":"2019-08-12T07:15:07","modified_gmt":"2019-08-12T13:15:07","slug":"communicating-between-directives-in-angularjs","status":"publish","type":"post","link":"https:\/\/thesmithfam.org\/blog\/2012\/12\/17\/communicating-between-directives-in-angularjs\/","title":{"rendered":"Communication Between Directives in AngularJS"},"content":{"rendered":"<style>\nimg {\n  box-shadow: 0 0 10px #aaa;\n  border: 1px solid #999;\n  border-radius: 5px;\n  padding: 10px !important;\n}\ntt {\n  background: #f4f4ff !important;\n  padding: 2px 4px !important;\n  border: 1px solid #e6e6ff !important;\n  border-radius: 4px !important;\n}\n.syntaxhighlighter table td.code .container {\n  padding: 5px !important;\n}\n<\/style>\n<p>Warning: This article is long and thorough. If you&#8217;re in a hurry, you can skip straight to the final product here:<\/p>\n<p><a href=\"http:\/\/plnkr.co\/edit\/6KxHY8ZpE83Z2PeNWlYi?p=preview\">http:\/\/plnkr.co\/edit\/6KxHY8ZpE83Z2PeNWlYi?p=preview<\/a><\/p>\n<h2>Prerequisites to this article<\/h2>\n<p>Before reading this, get to know these AngularJS terms. You don&#8217;t need too much depth, but you need to know what they are:<\/p>\n<ul>\n<li><a href=\"http:\/\/docs.angularjs.org\/guide\/directive\">Directive<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/guide\/scope\">Scope<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/guide\/dev_guide.mvc.understanding_controller\">Controller<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/guide\/dev_guide.services.injecting_controllers\">Injecting services into controllers<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/api\/ng.directive:ngShow\">ng-show<\/a> and <a href=\"http:\/\/docs.angularjs.org\/api\/ng.directive:ngHide\">ng-hide<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/api\/ng.directive:ngClick\">ng-click<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/api\/ng.directive:ngModel\">ng-model<\/a><\/li>\n<li><a href=\"http:\/\/docs.angularjs.org\/api\/ng.directive:ngRepeat\">ng-repeat<\/a><\/li>\n<\/ul>\n<p>You should also peruse the <a href=\"http:\/\/docs.angularjs.org\/guide\/\">Angular Developer Guide<\/a>, but don&#8217;t feel bad if a lot of the jargon does not make much sense at first.<\/p>\n<h2>Step 0: Roadmap<\/h2>\n<p>We&#8217;re going to create two custom directives that communicate with each other. We&#8217;ll really dig deep into the first directive, explaining every line of code as we go.<\/p>\n<p>Then we&#8217;ll glue the directive to a controller via a scope object.<\/p>\n<p>Lastly, we&#8217;ll create a second directive and glue it all together.<\/p>\n<h2>Step 1: A basic directive, dissected<\/h2>\n<p>For this example, we&#8217;ll create a custom search box that can be placed in our app with a custom <tt>&lt;my-search-box&gt;<\/tt> element. This directive causes Angular to convert <tt>&lt;my-search-box&gt;<\/tt> in your HTML into <tt>&lt;span&gt;My Custom Search Box&lt;\/span&gt;<\/tt>. This is not useful yet, but it will become immensely useful as we grow this concept in a few paragraphs.<\/p>\n<p>We&#8217;ll create a file called &#8220;app.js&#8221; with this content:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nangular.module(&quot;MyApp&quot;, &#x5B;]).\r\n  directive('mySearchBox', function() {\r\n    return {\r\n      restrict: 'E',\r\n      replace: true,\r\n      template: '&lt;span&gt;My Custom Search Box&lt;\/span&gt;'\r\n    };\r\n  });\r\n<\/pre>\n<p>Let&#8217;s walk through each line of that directive:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nangular.module(&quot;MyApp&quot;, &#x5B;]).\r\n<\/pre>\n<p>This line declares a new module called &#8220;MyApp&#8221;. The empty array to the right can contain the names of other modules on which this module depends (this is where you would put AngularUI modules for example if you want to use AngularUI). In this case, this module happens to be our &#8220;main&#8221; application module, but Angular really doesn&#8217;t know that from this line of code. That happens in the HTML with <tt>&lt;html ng-app=\"MyApp\"&gt;<\/tt>. Also, you only declare your main application module once, even if you have many directives. There are ways to look up your module if your code spans multiple files, or you can just create a global variable to reference your module and use that when building your directive.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n  directive('mySearchBox', function() {\r\n<\/pre>\n<p>Here we are declaring a new directive. Notice that we camel case the directive name. When Angular encounters <tt>&lt;my-search-box&gt;<\/tt> in the HTML, it will normalize that into &#8220;mySearchBox&#8221; to look up the directive. Thus, &#8220;mySearchBox&#8221; is called the &#8220;normalized&#8221; name.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    return {\r\n<\/pre>\n<p>Angular expects the directive function to return an object with properties that describe the directive.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n      restrict: 'E',\r\n<\/pre>\n<p>This tells Angular that &#8220;my-search-box&#8221; must be an <b>element<\/b>. Angular directives can also exist as HTML attributes, HTML class names, and even HTML comments (!). It&#8217;s okay if this doesn&#8217;t make sense yet.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n      replace: true,\r\n<\/pre>\n<p>This tells Angular to fully replace <tt>&lt;my-search-box&gt;<\/tt> with the directive&#8217;s template HTML. Alternatively, Angular can <b>add<\/b> the directive&#8217;s template HTML to the <tt>&lt;my-search-box&gt;<\/tt> element as a <b>child<\/b> element. For our example, we want Angular to fully replace <tt>&lt;my-search-box&gt;<\/tt> because <tt>&lt;my-search-box&gt;<\/tt> is not a valid HTML element name. You can imagine wanting Angular to simply <b>augment<\/b> an element with child elements in some scenarios, but not this example. We&#8217;re effectively creating a &#8220;widget&#8221; that can be instantiated and reused in our HTML.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n      template: '&lt;span&gt;My Custom Search Box&lt;\/span&gt;'\r\n<\/pre>\n<p>This is the directive&#8217;s HTML template that will be rendered by the browser. I don&#8217;t recommend using hard-coded template strings in your directives like I&#8217;ve done here. I do it this way to make the example clear. Normally, I use the <tt>templateUrl<\/tt> property and serve the HTML as a &#8220;partial&#8221; from my web server. Angular caches these partials, and you can even pre-load them when your app loads. This way, I can use server-side template technologies for things like localization. Although, for the best performance, I recommend that you serve these partials statically from a CDN or other fast caching service.<\/p>\n<p>Now we can use this directive in our HTML like this:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;html ng-app=&quot;MyApp&quot;&gt;\r\n  &lt;head&gt;\r\n    &lt;script src=&quot;http:\/\/ajax.googleapis.com\/ajax\/libs\/angularjs\/1.0.3\/angular.min.js&quot;&gt;&lt;\/script&gt;\r\n    &lt;script src=&quot;app.js&quot;&gt;&lt;\/script&gt;\r\n  &lt;\/head&gt;\r\n  &lt;body&gt; \r\n      &lt;my-search-box&gt;&lt;\/my-search-box&gt;\r\n  &lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/pre>\n<p>When you visit that page in your browser, you&#8217;ll see &#8220;My Custom Search Box&#8221; if all went well above.<\/p>\n<p>So far this is a pretty useless directive, but we&#8217;are about to take it to the next level.<\/p>\n<h2>Step 2: Giving your directive its own scope<\/h2>\n<p>Each instance of a directive has its own scope. And of course, the scope is a child of the enclosing scope where you instantiated the directive in the HTML. For example, if your directive exists inside a <tt>&lt;div ng-controller=\"MyController\"&gt;<\/tt>, then your directive&#8217;s scope will be a child of <tt>MyController<\/tt>&#8216;s <tt>$scope<\/tt>.<\/p>\n<p>For example, the following HTML uses two <tt>&lt;my-search-box&gt;<\/tt> elements. Angular gives each <tt>&lt;my-search-box&gt;<\/tt> its own independent scope:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n  &lt;body&gt; \r\n      &lt;my-search-box&gt;&lt;\/my-search-box&gt;\r\n      &lt;my-search-box&gt;&lt;\/my-search-box&gt;\r\n  &lt;\/body&gt;\r\n<\/pre>\n<p>Let&#8217;s define our directive&#8217;s interface to the outside world using the <tt>scope<\/tt> property. Our interface will have two values: <tt>searchText<\/tt> and <tt>isSearching<\/tt>. We will use <tt>searchText<\/tt> to store the user&#8217;s search text that they enter into an <tt>&lt;input&gt;<\/tt> box, and we&#8217;ll use <tt>isSearching<\/tt> to tell the directive when a search is in progress.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nangular.module(&quot;MyApp&quot;, &#x5B;]).\r\n  directive('mySearchBox', function() {\r\n    return {\r\n      restrict: 'E',\r\n      replace: true,\r\n      scope: {\r\n        searchText: '=',\r\n        isSearching: '='\r\n      },\r\n      template: '&lt;span&gt;My Custom Search Box&lt;\/span&gt;'\r\n    };\r\n  });\r\n<\/pre>\n<p>Did you see the <tt>scope = {...}<\/tt> property above? That defines the public elements of this directive&#8217;s scope. Notice how we used <tt>'='<\/tt>? That tells Angular that we want a scope variable to have <b>two way binding<\/b> to the outside world. This is part of the directive&#8217;s HTML interface. This allows callers to use our directive like this:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;my-search-box\r\n  search-text=&quot;someScopeVariable&quot;\r\n  is-searching=&quot;someOtherScopeVariable&quot;&gt;\r\n&lt;\/my-search-box&gt;\r\n<\/pre>\n<p>In other words, the directive allows outside callers to <b>bind<\/b> their own scope variables to this directive&#8217;s <tt>searchText<\/tt> and <tt>isSearching<\/tt> variables. This is how you communicate with the directive from the outside world.<\/p>\n<p>The variables <tt>someScopeVariable<\/tt> and <tt>someOtherScopeVariable<\/tt> come from the <b>enclosing<\/b> scope, which usually is managed by a controller outside the directive. If, for example, we had <tt>&lt;div ng-controller=\"MyController\"&gt;<\/tt> enclosing <tt>&lt;my-search-box&gt;<\/tt>, then <tt>someScopeVariable<\/tt> and <tt>someOtherScopeVariable<\/tt> would be managed by <tt>MyController<\/tt>.<\/p>\n<p>In the code above, the <tt>search-text<\/tt> gets normalized into <tt>searchText<\/tt> in the directive&#8217;s scope. Likewise, <tt>is-searching<\/tt> becomes <tt>isSearching<\/tt>.<\/p>\n<p>When we assign <tt>search-text=\"someScopeVariable\"<\/tt>, we are telling Angular to bind this directive&#8217;s <tt>searchText<\/tt> scope variable to a scope variable from the enclosing scope called <tt>someScopeVariable<\/tt>. Any time the enclosing scope&#8217;s <tt>someScopeVariable<\/tt> changes, the directive&#8217;s scope variable <tt>searchText<\/tt> will also change. And it works in the other direction too. Any time the directive changes its <tt>searchText<\/tt> variable, Angular will automatically change the enclosing scope&#8217;s <tt>someScopeVariable<\/tt> to match.<\/p>\n<p>These scope variables are useless unless we also make them visible somehow, so let&#8217;s modify our template HTML to use them. While we&#8217;re at it, let&#8217;s make this actually look like a search box instead of a simple piece of text:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nangular.module(&quot;MyApp&quot;, &#x5B;]).\r\n  directive('mySearchBox', function() {\r\n    return {\r\n      restrict: 'E',\r\n      scope: {\r\n        searchText: '=',\r\n        isSearching: '='\r\n      },\r\n      controller: function($scope) {\r\n        $scope.localSearchText = '';\r\n        $scope.clearSearch = function() {\r\n          $scope.searchText = &quot;&quot;;\r\n          $scope.localSearchText = &quot;&quot;;\r\n        };\r\n        $scope.doSearch = function() {\r\n          $scope.searchText = $scope.localSearchText;\r\n        };\r\n      },\r\n      replace: true,\r\n      template:\r\n      '&lt;form&gt;' +\r\n        '&lt;div&gt;' +\r\n          '&lt;input ng-model=&quot;localSearchText&quot; type=&quot;text&quot; \/&gt;' +\r\n        '&lt;\/div&gt;' +\r\n        '&lt;div&gt;' +\r\n          '&lt;button ng-click=&quot;clearSearch()&quot; class=&quot;btn btn-small&quot;&gt;Clear&lt;\/button&gt;' +\r\n          '&lt;button ng-click=&quot;doSearch()&quot;    class=&quot;btn btn-small&quot;&gt;Search&lt;\/button&gt;' +\r\n        '&lt;\/div&gt; ' +\r\n        '&lt;div ng-show=&quot;isSearching&quot;&gt;' +\r\n          '&lt;img ng-show=&quot;isSearching&quot; src=&quot;http:\/\/loadinggif.com\/images\/image-selection\/3.gif&quot; \/&gt; ' +\r\n          'Searching...' +\r\n        '&lt;\/div&gt;' +\r\n      '&lt;\/form&gt;'\r\n    };\r\n  })\r\n<\/pre>\n<p>Remember, I suggest you use <tt>templateUrl<\/tt> instead of <tt>template<\/tt> when your HTML starts to grow like this.<\/p>\n<p>Now we have a search box form that lets the user enter some search terms, which we store in the directive&#8217;s scope as <tt>localSearchText<\/tt>. Notice that we didn&#8217;t put <tt>localSearchText<\/tt> in the <tt>scope: {&hellip;}<\/tt> definition, because it needs no external binding. In other words, this is a &#8220;private&#8221; scope variable that the directive uses to store the human text input until we are ready to actually do the search. This is because we don&#8217;t want every single keystroke to initiate a search. Only when the user clicks the &#8220;Search&#8221; button.<\/p>\n<p>Notice also that we added a controller with <tt>controller: function($scope) {...}<\/tt>. This code defines a typical controller so our directive can take action in response to user input, like button clicks with <tt>ng-click<\/tt>.<\/p>\n<p>This HTML also provides a &#8220;Clear&#8221; button to zero out the search box and a spinner to show when the search is in progress. The directive relies on outside callers to tell it when a search is in progress by setting the <tt>isSearching<\/tt> variable to a &#8220;truthy&#8221; value.<\/p>\n<p>After making these changes to <tt>app.js<\/tt>, our page should look like this:<\/p>\n<p><img decoding=\"async\" src=\"\/images\/my-search-box-1.png\" \/><\/p>\n<p>Now that directive is finished. Notice it doesn&#8217;t do much. It requires an outsider to stimulate it into action.<\/p>\n<h2>Step 3: Creating a Controller<\/h2>\n<p>Let&#8217;s create a controller that communicates with the directive we wrote. This isn&#8217;t strictly required to allow two directives to communicate, but in most cases it will be necessary because someone has to glue them together with the business logic specific to your application. This is a job well suited to an Angular controller.<\/p>\n<p>Let&#8217;s make a simulated city search that allows the user to search for cities. Because it&#8217;s an example, the search will always return the same results.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;div ng-controller=&quot;CitySearchController&quot;&gt;\r\n  &lt;h1&gt;Search for Cities&lt;\/h1&gt; \r\n  &lt;my-search-box search-text=&quot;citySearchText&quot; is-searching=&quot;isSearchingForCities&quot;&gt;&lt;\/my-search-box&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>And the accompanying controller, which I placed in <tt>app.js<\/tt>:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nfunction CitySearchController($scope, $timeout) {\r\n  $scope.$watch(&quot;citySearchText&quot;, function(citySearchText) {\r\n    $scope.citySearchResults = &#x5B;];\r\n    if (citySearchText) {\r\n      $scope.isSearchingForCities = true;\r\n      $timeout(function() {\r\n        \/\/ simulated search that always gives the same results\r\n        $scope.isSearchingForCities = false;\r\n        $scope.citySearchResults = &#x5B;'New York', 'London', 'Paris', 'Moab'];\r\n      }, 1000);\r\n    } else {\r\n      $scope.isSearchingForCities = false;\r\n    }\r\n  });\r\n}\r\n<\/pre>\n<p>This controller&#8217;s <tt>$scope.citySearchText<\/tt> and <tt>$scope.isSearchingForCities<\/tt> variables are <b>bound<\/b> to the directive&#8217;s scope variables <tt>searchText<\/tt> and <tt>isSearching<\/tt> because of the HTML attributes that we specified on <tt>&lt;my-search-box&gt;<\/tt>.<\/p>\n<p>This controller is pretty basic, so I won&#8217;t describe every line of code. All it does is <tt>$watch()<\/tt> for changes to <tt>citySearchText<\/tt> and get some fake search results with Angular&#8217;s <tt>$timeout<\/tt> service.<\/p>\n<p>Because of Angular&#8217;s excellent isolation-centric design, this controller would be very easy to write unit tests for, but that&#8217;s another article.<\/p>\n<p>When you visit the page, you should now see a search box. If you enter some text into the input box and click &#8220;Search&#8221;, you&#8217;ll see a spinner for 1 second, which then disappears:<\/p>\n<p><img decoding=\"async\" src=\"\/images\/my-search-box-2.png\" \/><\/p>\n<h2>Step 4: Finally add a second directive<\/h2>\n<p>Now we&#8217;re ready to add another directive. For this example, we&#8217;ll create a search <b>results<\/b> directive. This directive has almost the same public interface (i.e., scope) as the <tt>&lt;my-search-box&gt;<\/tt> directive, with one extra variable: the actual search results that caller wants to display.<\/p>\n<p>It looks like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n directive('mySearchResults', function() {\r\n    return {\r\n      restrict: 'E',\r\n      transclude: true,\r\n      scope: {\r\n        isSearching: '=',\r\n        searchResults: '=',\r\n        searchText: '='\r\n      },\r\n      replace: true,\r\n      template:\r\n        '&lt;div ng-hide=&quot;isSearching&quot;&gt;' +\r\n          '&lt;h4 ng-show=&quot;searchResults&quot;&gt;Found {{searchResults.length}} Search Results For &quot;{{searchText}}&quot;:&lt;\/h4&gt;' +\r\n          '&lt;ul ng-show=&quot;searchResults&quot;&gt;' +\r\n            '&lt;li ng-repeat=&quot;searchResult in searchResults&quot;&gt;' +\r\n              '{{searchResult}}' +\r\n            '&lt;\/li&gt;' +\r\n          '&lt;\/ul&gt;' +\r\n        '&lt;\/div&gt;'\r\n    };\r\n  });\r\n<\/pre>\n<p>Everything should look familiar from your study of the first directive. There are no new concepts here. Let&#8217;s use our directive in our HTML:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n  &lt;div ng-controller=&quot;CitySearchController&quot; style=&quot;margin: 20px&quot;&gt;\r\n      &lt;h1&gt;Search for Cities&lt;\/h1&gt; \r\n      &lt;my-search-box search-text=&quot;citySearchText&quot; is-searching=&quot;isSearchingForCities&quot;&gt;&lt;\/my-search-box&gt;\r\n      &lt;my-search-results is-searching=&quot;isSearchingForCities&quot; search-results=&quot;citySearchResults&quot; search-text=&quot;citySearchText&quot;&gt;&lt;\/my-search-results&gt;\r\n    &lt;\/div&gt;\r\n<\/pre>\n<p>Now your page should show some search results after clicking the &#8220;Search&#8221; button and waiting for 1 second:<\/p>\n<p><img decoding=\"async\" src=\"\/images\/my-search-box-3.png\" \/><\/p>\n<p>Just to prove that there is indeed <b>zero coupling<\/b> between the two directives and the controller, I added a second controller and a second instance of each directive to search for fruits, which you can see in the plunk below.<\/p>\n<h2>The Finished Product<\/h2>\n<p>Here it is: <a href=\"http:\/\/plnkr.co\/edit\/6KxHY8ZpE83Z2PeNWlYi?p=preview\">http:\/\/plnkr.co\/edit\/6KxHY8ZpE83Z2PeNWlYi?p=preview<\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>From the sheer length of this article, you may think that this is complicated, but the reality is that it only took me about 30 minutes to whip together the working example in the plunk.<\/p>\n<p>Main points I hope you took from this article:<\/p>\n<ul>\n<li>Directives are easy to create.<\/li>\n<li>Directives have their own scope<\/li>\n<li>Directives can communicate with the outside world via HTML attributes<\/li>\n<li>Directives encourage loose coupling<\/li>\n<li>Directives encourage reuse and UI consistency<\/li>\n<li>Directives are easy to test (well, this is a future article)<\/li>\n<li>Controllers can use directives with zero coupling<\/li>\n<li>The Prime Directive has nothing to do with AngularJS (bummer)<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Warning: This article is long and thorough. If you&#8217;re in a hurry, you can skip straight to the final product here: http:\/\/plnkr.co\/edit\/6KxHY8ZpE83Z2PeNWlYi?p=preview Prerequisites to this article Before reading this, get to know these AngularJS terms. You don&#8217;t need too much depth, but you need to know what they are: Directive Scope Controller Injecting services into [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-1249","post","type-post","status-publish","format-standard","hentry","category-code-and-cruft"],"_links":{"self":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts\/1249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/comments?post=1249"}],"version-history":[{"count":99,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts\/1249\/revisions"}],"predecessor-version":[{"id":1501,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts\/1249\/revisions\/1501"}],"wp:attachment":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/media?parent=1249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/categories?post=1249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/tags?post=1249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}