Можно ли использовать параметризованные шаблоны URL с помощью службы angular $http

Я использую $resource для моего RESTful api и люблю шаблон с параметризованным URL-адресом, например 'api/clients/:clientId'

Это отлично работает для операций CRUD. Некоторые из моих api - это просто отчеты или конечные точки только для чтения без необходимости полного лечения RESTful. Я чувствовал, что было слишком сложно использовать $resource для них, и вместо этого использовала пользовательскую службу данных с $http.

Единственный недостаток - потерять параметризованные шаблоны URL. Я хотел бы определить url как 'api/clients/:clientId/orders/:orderId' и просто пройти { clientId: 1, orderId: 1 }. Я понимаю, что могу построить url динамически, но надеялся, что $http поддерживает параметризованный шаблон, и я его еще не нашел.

Все лучшее

ОБНОВЛЕНИЕ 7/5

Слово, которое я отсутствовал в моих поисках, это "Интерполяция". Дополнительная информация появляется, когда я ищу "интерполяцию URL" в angular $http '. Короткий ответ выглядит так: "Нет" $http не поддерживает интерполяцию url. Однако есть несколько довольно простых способов сделать это.

1. Использовать $интерполяцию:

Документация для $interpolate здесь

var exp = $interpolate('/api/clients/{{clientId}}/jobs/{{jobId}}', false, null, true);
var url = exp({ clientId: 1, jobId: 1 });


2. Напишите свою собственную интерполяционную функцию URL

У Бен Наделя есть отличная статья в этой точной теме здесь.


3. Украдите функциональность прямо из angular -resource

Проверьте setUrlParams на Route.prototype в angular -resource.js. Это довольно просто.

Пример службы данных с использованием интерполяции $

(function () {
    'use strict';

    var serviceId = 'dataservice.jobsReports';

    angular.module('app').factory(serviceId, ['$http', '$interpolate', function ($http, $interpolate) {

        var _urlBase = 'http://localhost:59380/api';
        var _endPoints = {
            getJobsByClient: {
                url: 'Clients/{{clientId}}/Jobs',
                useUrlInterpolation: true,
                interpolateFunc: null
            }
        };

        // Create the interpolate functions when service is instantiated
        angular.forEach(_endPoints, function (value, key) {
            if (value.useUrlInterpolation) {
                value.interpolateFunc = $interpolate(_urlBase + '/' + value.url, false, null, true);
            }
        });

        return {
            getJobsByClient: function (clientId) {
                var url = _endPoints.getJobsByClient.interpolateFunc({ clientId: clientId });
                return $http.get(url);
            }
        };

    }]);

})();

Ответы

Ответ 1

Чтобы это не было "без ответа", когда было получено ответ...

1. Использовать $интерполяцию:

Документация для $interpolate здесь

var exp = $interpolate('/api/clients/{{clientId}}/jobs/{{jobId}}', false, null, true);
var url = exp({ clientId: 1, jobId: 1 });


2. Напишите свою собственную интерполяционную функцию URL

У Бен Наделя есть отличный пост по этой точной теме здесь.


3. Украдите функциональность прямо из angular -resource

Проверьте setUrlParams на Route.prototype в angular -resource.js. Это довольно просто.

Пример службы данных с использованием интерполяции $

(function () {
    'use strict';

    var serviceId = 'dataservice.jobsReports';

    angular.module('app').factory(serviceId, ['$http', '$interpolate', function ($http, $interpolate) {

        var _urlBase = 'http://localhost:59380/api';
        var _endPoints = {
            getJobsByClient: {
                url: 'Clients/{{clientId}}/Jobs',
                useUrlInterpolation: true,
                interpolateFunc: null
            }
        };

        // Create the interpolate functions when service is instantiated
        angular.forEach(_endPoints, function (value, key) {
            if (value.useUrlInterpolation) {
                value.interpolateFunc = $interpolate(_urlBase + '/' + value.url, false, null, true);
            }
        });

        return {
            getJobsByClient: function (clientId) {
                var url = _endPoints.getJobsByClient.interpolateFunc({ clientId: clientId });
                return $http.get(url);
            }
        };

    }]);

})();

Ответ 2

Для шаблона URL существует четко определенная рекомендация: RFC 6570

Вы можете найти одну реализацию в Github: bramstein/url-template

Это довольно просто. Вот услуга AngularJS, использующая библиотеку, реализующую RFC 6570:

var app=angular.module('demo',[]);


app.service('UserStore',function () {
  var baseUrl=urltemplate.parse('/rest/v1/users{/_id}');
  return {
    load:function(id){
      return $http.get(baseUrl.expand({_id:id}));
    },
    save:function (profile) {
      return baseUrl.expand(profile);
      //return $http.post(baseUrl.expand(profile),profile);
    },
    list:function (id) {

    }
  }
});

app.controller('demoCtrl',function(UserStore){
  this.postUrlOfNewUser=UserStore.save({name:"jhon"});
  this.postUrlOfExistingUser=UserStore.save({_id:42,name:"Arthur",accessory:"towel"});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdn.rawgit.com/bramstein/url-template/master/lib/url-template.js"></script>
<div ng-app="demo">
  <div ng-controller="demoCtrl as ctrl">
    <div>New user POST URL: {{ctrl.postUrlOfNewUser}}</div>
    <div>Existing user POST URL: {{ctrl.postUrlOfExistingUser}}</div>
  </div>
</div>
<script>
</script>