Newby to Angular so apologies if a stupid question. Have checked other questions on dataversity, stack overflow, google ... checked w3c and attempted several "try it and see solutions" but just can't get this to play ball.

Basically, i am using angular to bind the results of a SPARQL query on classes and number of classes in a dataset/query using Fuseki Server 1-1.1.2 endpoint (SPARQL 1.1). (See code below after question).

This nicely lists the class name in URI format and a count of it's instances in URI format but I want to only see the characters after the "#" for "class" in the results rather than the whole URI.

I initially tried doing this in the SPARQL query using REPLACE and STRAFTER functions in the query (i.e. SELECT (strafter(str(?class),"#") AS ?className)) which works fine in Fuseki directly but returns blank results in attempted angular bindings.

From reading other answers, I'm aware of getLocalName() and that not all data will have a local name after the "#" but I need to access the part after the "#" in javascript. So my question is this ....

In order to perform URI/string manipulation on the returned data, I would like to know how to bind individual data items returned to individual scope variables i.e. instead of $scope.results = response.results.bindings Can I do something like $scope.results.class = response.results.bindings.class.value? (It didn't work when I tried it nor did passing "results.bindings.class.value" to a string delineating function as I couldn't figure out how to then invoke this in ng-repeat).

So please in summary could you advise me how to bind individual json "values" to named $scope variables?

Any help gratefully received. I have to do it using SPARQL, javascript/HTML/angular.

Here is my code.

<!DOCTYPE html>
<html >
<script src=     "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="queryCtrl"><table>
 <tr ng-repeat="x in results">
    <td>{{x.class.value}}</td>
    <td>{{x.count.value}}</td>
  </tr>
</table></div>

<script>
var app = angular.module('myApp', []);
app.controller('queryCtrl', function($scope, $http) {
   var query = encodeURIComponent("SELECT  ?class (COUNT(?s) AS ?count ) { ?    s a ?class } GROUP BY ?class ORDER BY ?count");
   var endpoint = "http://localhost:3030/dataset/query";
   $scope.results = [];
   $http.get("http://localhost:3030/dataset/query?    query="+query+"&output=json")
   .success(function (response) {
    $scope.results = response.results.bindings;
    /* for debugging*/
    if ( window.console && window.console.log ) {
       // console is available, write message if something has happened
       console.log(response.results);
    }
   });

});
</script>

</body>
</html>
2

There are 2 best solutions below

1
On BEST ANSWER

If I understand your question correctly, you want to bind to the json data but only show the substring after # in the view for the class values. This can be done by applying a filter on x.class.value. So here's how you would do it:

Assuming your data is returned in the following form:

{"results": {"bindings": [
  {"class": {"value": "http://foo.bar#foo"}, "count": {"value": 123}}
  ]
}}

Retrieve a json file and populate the scope variable with the return value:

app.controller('queryCtrl', function($scope, $http) {
  $scope.results = [];
  $http.get("results.json")
    .then(function (response) {
      $scope.results = response.data.results.bindings;
    });
});

Apply a filter in the view:

<td>{{x.class.value | myFilter}}</td>

Define the filter to extract the substring after the #:

app.filter('myFilter', function() {
  return function(name) {
    var n = name.indexOf('#');// or lastIndexOf
    return name.substring(n + 1);
  }
});

Here's a working plunker.

p.s. you can move all the querying logic in your example to a reusable service/factory, which would keep your app cleaner.

2
On

Spent a day on this and one solution is just to convert the class URI representation to a string in the SPARQL query and use a custom angular filter in the ng-repeat.

So instead of

  <tr ng-repeat="x in results">
    <td>{{ x.class.value}}</td>
    <td>{{ x.count.value }}</td>
  </tr>

I have

  <tr ng-repeat="x in results">
    <!--<td>{{ x }}</td>-->
    <td>{{ x.className.value | localClassName}}</td>
    <td>{{ x.count.value }}</td>
  </tr>

Instead of

SELECT ?class (COUNT(?s) AS ?count) {?s a ?class} GROUP BY ?class ORDER BY     DESC(?count)

I have

SELECT (str(?class) AS ?className) (COUNT(?s) AS ?count) {?s a ?class} GROUP     BY ?class ORDER BY DESC(?count)

and appended to the angular.module.controller is the new filter "localClassName"

.filter("localClassName", function(){
        return function(value){
            /*var startName = value.indexOf("#") + 1;*/
            return String(value).slice(value.indexOf("#") + 1);
        }
   })

Entire code now reads as this:

<!DOCTYPE html>
<html>
<script src=         "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="queryCtrl">

<table>
  <tr ng-repeat="x in results">
    <td>{{ x.className.value | localClassName}}</td>
    <td>{{ x.count.value }}</td>
  </tr>
</table>

</div>

<script>
var app = angular.module('myApp', []);
app.controller('queryCtrl', function($scope, $http) {
   var query = encodeURIComponent("SELECT (str(?class) AS ?className)     (COUNT(?s) AS ?count) {?s a ?class} GROUP BY ?class ORDER BY DESC(?count)");
   var endpoint = "http://localhost:3030/dataset/query";
   $http.get("http://localhost:3030/dataset/query?    query="+query+"&output=json&stylesheet=")
   .success(function (response) {
    $scope.results = response.results.bindings;
    /* for debugging*/
    if ( window.console && window.console.log ) {
       // console is available, write message if something has happened
       console.log(response.results);
    }

   })
}).
   filter("localClassName", function(){
        return function(value){
            /*var startName = value.indexOf("#") + 1;*/
            return String(value).slice(value.indexOf("#") + 1);
        }
   })

</script>

</body>
</html>

and it works a treat!