Have a expression error in ui-sref - angularjs

I am working through the ui-router docs. I have a decent feel for what I am trying to do with ui-sref. In the bottom td I am adding ui-sref to the desired href. I made sure to call the state that I want to fire and the brackets are the route Params that I am trying to create.
the problem is though that I am getting Syntax Error: Token '.' is at column {2} of the expression [{3}] starting at [{4}] from the Angular docs.
I made sure to reference some additional info incase I am missing in any part of my code.
<div class="row" >
<div class="panel panel-primary">
<div class="panel-heading">
Customer List
</div>
<div class="panel-body">
Filter: <input type="text" ng-model="customerFilter">
</div>
<table class="table table-striped table-responsive">
<tr>
<th ng-click="ctrl.doSort('name')">Name</th>
<th ng-click="ctrl.doSort('city')">City</th>
<th ng-click="ctrl.doSort('orderTotal')">order total</th>
<th ng-click="ctrl.doSort('joined')">joined</th>
<th> </th>
</tr>
<tr data-ng-repeat = "cust in ctrl.customers |filter: customerFilter| orderBy:ctrl.sortBy:ctrl.reverse">
<td>{{cust.name | uppercase}}</td>
<td>{{cust.city}}</td>
<td>{{cust.orderTotal | currency}}</td>
<td>{{cust.joined |date}}</td>
<td><a ui-sref="orders({ctrl.cust.id})">View Orders</a></td>
</tr>
</table>
</div>
<span>Total customers: {{ctrl.customers.length}}</span>
</div>
Here is the top part of my controller. I am working with controllerAs and trying to get more used to the John Papa style guide
angular
.module('app.customers')
.controller('CustomerController', CustomerController);
function CustomerController($stateParams) {
var vm = this;
// customerId comes from url param
console.log($stateParams);
var customerId = $stateParams.customerId;
vm.orders = null;
I am getting back an empty object for $stateParams
My route file is broken up as specific as I could make it. I created a view object, created a main view and referenced it in the html. I made a resolve object that will take the $stateParams
angular
.module('app.customers')
.config(config);
function config($stateProvider) {
console.log('customers route')
$stateProvider
.state('customers',{
url:'/customers',
views: {
"main#": {
templateUrl: './components/customers/customers.html',
controller: 'CustomerController',
controllerAs: 'ctrl'
}
},
resolve: {
customerId: ['$stateParams', function($stateParams) {
return $stateParams.customerId;
}]
}
})
};
However, I am just going to the templateUrl I created with no data and the url is not getting the id.
Here is my orders controller
(function() {
'use strict';
angular
.module('app.orders')
.controller('OrdersController', OrdersController);
function OrdersController($stateParams) {
console.log('in orders');
var vm = this;
vm.title = "Customer Orders";
}
}());
This is the route that I set up for orders. I made sure to reference :Id each contact id.
(function() {
'use strict';
angular
.module('app.orders')
.config(config);
function config($stateProvider) {
$stateProvider
.state('orders',{
url:'/orders:customerId',
templateUrl: './components/orders/orders.html',
controller: 'OrdersController',
controllerAs: 'ctrl'
})
// $locationProvider.html5Mode(false);
};
})();

Firstly, state should define the parameter. It could be part of url or params : {} (or both), but at least some...
// params
.state('customers',{
url:'/customers',
params: { customerId : null }
...
// url
.state('customers',{
url:'/customers/:customerId',
...
// url & params
.state('customers',{
url:'/customers/:customerId',
params: { customerId : 1 } // default value
...
Having this, we can create ui-sref like this:
// instead of this
<td><a ui-sref="orders({ctrl.cust.id})">View Orders</a></td>
// we need object with name customerId and its value
<td><a ui-sref="orders({customerId: ctrl.cust.id})">View Orders</a></td>
For more details check this Q & A:
How to pass parameters using ui-sref in ui-router to controller

I think one part of the issue is that ctrl.cust.id should just be cust.id

Related

How to route to an api value from ng-repeat?

I have an api that returns a list of values, i want to be able to click the name of the driver in the api to route to driver details but i cant figure out how to do that.
This is how it looks now
Alternative Look
This is how it should look when i click on the name from ng-repeat from api
i am new to angular and its very confusing atm.
this is my controller.
import { app } from '../index';
app.controller("api", function ($scope, $http) {
$scope.Naziv = "Driver Championship Standings - 2013";
$scope.NazivH1 = "Driver Championship";
$scope.TopDrivers = function () {
console.log("i been pressed");
$http.get("https://ergast.com/api/f1/2013/driverStandings.json")
.then(function successCallback(response) {
$scope.drivers = response.data.MRData.StandingsTable.StandingsLists[0].DriverStandings;
console.log("response.data.MRData.StandingsTable.StandingsLists.0.DriverStandings");
console.log(response.data.MRData.StandingsTable.StandingsLists[0].DriverStandings);
}, function errorCallback(response) {
console.log("Unable to perform get request");
});
}
my routes:
app.config(function($routeProvider, $locationProvider) {
$locationProvider.hashPrefix("!");
$routeProvider
.when("/drivers", {
templateUrl: "./src/pageDetails/drivers.html",
})
.when("/teams", {
templateUrl: "./src/pageDetails/teams.html",
})
.when("/races", {
templateUrl: "./src/pageDetails/races.html",
})
.otherwise({
redirect: "./src/pageDetails/default.html",
});
});
this is the how my template looks.
<div ng-controller="api" ng-init="TopDrivers()">
<h1>{{NazivH1}}</h1>
<div id="modifyDiv">{{Naziv}}</div>
<!-- <button ng-click="TopDrivers()">Test Rest</button> -->
<div ng-repeat="x in drivers | orderBy: '+Points'">
<div id="divRow">
<table>
<tr id="tableRow"><td id="td1">Nb: {{x.position}}</td><td id="td2">{{x.Constructors[0].nationality}} {{x.Driver.givenName}} {{x.Driver.familyName}}</td><td id="td3">{{x.Constructors[0].name}}</td> <td id="td4">Points{{x.points}}</td> </tr>
</table>
</div>
</div>
</div>
firstly why do you have ng-repeat on div and not on <tr>? Do you want a separate div for each driver or do you want a separate row? I suggest you use ng-repeat on <tr> and also add a ng-click directive on your <tr> so whenever someone clicks a driver row, function gets executed on your controller and in that function you can route to the driver details like below:-
<tr ng-repeat="x in drivers | orderBy: '+Points'" ng-click="driverDetails(x.DriverId)" id="tableRow">
<td id="td1">Nb: {{x.position}}</td>
<td id="td2">{{x.Constructors[0].nationality}} {{x.Driver.givenName}} {{x.Driver.familyName}}</td>
<td id="td3">{{x.Constructors[0].name}}</td>
<td id="td4">Points{{x.points}}</td>
</tr>
now in your controller write the driverDetails function like below:-
$scope.driverDetails = function (driverId) {
$location.path('/driverDetails').search({ driverId: driverId });
};
in this function you are changing the url and appending the driverId as query string. Now in the routes add another route
.when("/driverDetails", {
templateUrl: "./src/pageDetails/driverdetails.html",
})
so when the driverDetails function is run in the controller, the driverdetails.html is loaded and you have the driverId in the query srting. Now in the driverdetails controller just retrieve the driverId and make call to your api for that specific driver
You need to add a driver details route with an optional parameter (something like /driver-detail/:id in the route definition). Pass it's own controller, a way to fetch the detail data (you might want to keep it in a service) and then add a ng-click event handler for when the user is in the drivers list ng-repeat and you pass the driver id in there.
Something like :
<tr id="tableRow" ng-click="goToDetail(x.id)">...</tr>
And in the controller :
$scope.goToDetail() = function(id) {
$location.path('/driver-detail/' + id)
}
Your route definition could look something like this :
.when('/driver-detail/:id', {
templateUrl: '...',
controller: function($scope, $stateParams) {
$scope.id = $stateParams.id;
...
}
}
But I strongly recommend you to upgrade your stack, even for AngularJS this is an old way to code - they introduced the component API and particularly for routing, the ui-router is a much more powerful alternative to the ngRouter. If you're starting a project, start with Angular CLI (currently Angular 7) and you'll collect a lot more feedback and find more online resources to guide you.

angular 1 - routing and api

Trying to write a simple SPA. Using MEAN.
API through node are all working.
Have set up routes in my main controller
// create the module and name it
var boardingApp = angular.module('boardingApp', ['ngRoute']);
boardingApp.config(function($routeProvider) {
$routeProvider
// route for the home page that lists all tenants
.when('/', {
templateUrl : 'js/templates/tenants.html',
controller : 'tenantsController'
})
// route for a specifc tenant
.when('/tenant/:id', {
templateUrl : 'js/templates/tenant.html',
controller : 'tenantController'
})
});
boardingApp.controller('tenantsController', ['$scope','$http','$log', function($scope, $http,$log) {
$http.get(URL + "/api/tenants")
.then(function(response){ $scope.details = response.data; });
}]);
boardingApp.controller('tenantController', ['$scope','$http','$location','$log', function($scope, $http, $location, $log) {
if ( $location.search().hasOwnProperty( 'id' ) ) {
var myid = $location.search()['id'];
console.log(myid)
myURL = URL + "/api/tenants/"+myid
console.log(myURL)
$http.get(myURL)
.then(function(response){ $scope.tenant = response.data; });
console.log($scope.tenant)
}
}]);
boardingApp.controller('readmeController', function($scope, $http) {
$scope.message = "This is the message"
});
the root route work finds calls the API generates a table. All good
then main part of that template is this
<tbody id="tenantsTable">
<tr ng:repeat = "tenant in details | filter : true: tenant.activeTenant ">
<td><a ng-href = "#/tenant.html?id={{tenant._id}}" >View</td>
<td>{{tenant.roomNumber}} </td>
<td>{{tenant.firstName}} </td>
<td>{{tenant.lastName}} </td>
<td>{{tenant.paymentFrequency}} </td>
<td>${{tenant.rentAmount}} </td>
<td> {{tenant.leaseEnd | date: 'dd MMM yyyy'}} </td>
</tr>
</tbody>
I want to click on the "View" link and pull data from DB for each tenant through and API call that just needs the Tenant id - standard stuff.
My controller is not picking up the request and when i click on the link on the Tennants page it just ends up blank.
what am i missing here? the api call s are all good and working fine
You anchor tab is incorrect, it should be in correct pattern like "#/tenant/{{tenant._id}}"
ng-href="#/tenant/{{tenant._id}}"
Additionally you should retrieve a route parameter inside tenantController by using $routeParams.id API instead of $location.search() which would be look for query parameter.

Filtering AngularJS Table Based Off Value In Separate Controller

Ok so I am very new to Angular, only been playing with it for three days now. I am running into an issue when trying to filter a table I created based on the value of a "select option" in another controller. Basically I have one controller that performs a REST call to populate a "select" menu dynamically. Then I have another controller that makes a separate REST call to populate a table. What I am trying to do is filter the table based off the "value" from the "selected" option. For example if I choose the "option" with a value of "2", the table would filter to only show results with an "ID" of "2". I may be going about this in a completely wrong way but from what I am reading I need to create a "service" to store the "value" of the "option" so that I can reference it in the controller that populates the table. If anyone could provide some incite on how to go about doing this I would greatly appreciate it. Please see my code bellow...
Angular Code
angular.module('restCalls',[])
// Controller for Project REST Call
.controller('displayProj',function($scope, $http) {
$http({type: "GET", url:"http://my_api_call/", headers: { "ACCEPT": "application/json;odata=verbose"}})
.success(function(data) {
$scope.results = data.d.results;
$scope.projects = [];
for(i=0; i < data.d.results.length; i++) {
$scope.projects.push({name: data.d.results[i].Title , id: data.d.results[i].Id});
};
$scope.getSelectedOption = function(value) {
console.log($scope.selectedProject.id);
};
});
})
// Controller for ChargeCode REST Call
.controller('displayCC',function($scope, $http) {
$http({type: "GET", url:"http://my_api_call/", headers: { "ACCEPT": "application/json;odata=verbose"}})
.success(function(data) {
$scope.results = data.d.results;
$scope.projects = [];
for(i=0; i < data.d.results.length; i++) {
$scope.projects.push({id: data.d.results[i].Master_x0020_ID, cc: data.d.results[i].Title, name: data.d.results[i].deltek_x0020_name});
}
})
});
HTML Code
<div data-ng-app="restCalls" class="ng-scope">
<div id="project_menu_select" data-ng-controller="displayProj" class="ng-scope">
<p class="ng-binding">ID of selected project is:​​​​ {{selecteProject.id}} </p>
<select data-ng-model="selectedProject" data-ng-options="project.name for project in projects" class="ng-pristine ng-valid ng-empty form-control ng-touched ng-untouched" data-ng-change="getSelectedOption()">
</select>​ </div>
<div id="charge_codes_table" data-ng-controller="displayCC" class="ng-scope">
<table class="table table-striped">
<thead>
<tr>
<th>Project ID</th>
<th>Charge Code</th>
<th>Deltek Name</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="project in projects">
<td data-ng-if="project.id == (option value)">{{project.id}}</td>
<td data-ng-if="project.id == (option value)">{{project.cc}}</td>
<td data-ng-if="project.id == (option value)">{{project.name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Anyway you have both table and select option in one page. Better to use single controller for both.
You can also use common parent controller for both of these controllers.
OR
You can use $rootScope to share the variables. Set as $rootScope.selectedValue = 2 from one controller and then you can access this as $rootScope.selectedValue from another controller.
OR
You can use services to share the functions and variables as follows,
app.service("shared", function () {
var selectedOption = {};
return {
getSelectedOption: function () {
return selectedOption;
},
setSelectedOption: function (value) {
selectedOption = value;
}
};
});

function not executing on different view

I am new to angular JS. I have created a simple page using ngRoute.
In the first view I have a table, and on clicking it redirects to second view.
But I have called two functions using ng-click the changeView functions is running fine. But the second function fails to execute on the second view.
But Its running fine if using on the first view itself.
Heres the code for first view
Angular.php
<div ng-app="myApp" ng-controller="dataCtr">
<table class='table table-striped'>
<thead>
<tr>
<td>Title</td>
<td>Stream</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr ng-repeat = "x in names | filter:filtr | filter:search" ng-click=" disp(x.id);changeView()">
<td >{{ x.Title }}</td>
<td>{{ x.Stream }}</td>
<td>{{ x.Price }}</td>
</tr>
</tbody>
</table>
</div>
heres the second View
details.php:
<div ng-app="myApp" ng-controller="dataCtr">
<div class="container">
SELECTED:<input type="textfield" ng-model="stxt">
</div>
</div>
heres the js file:
var app = angular.module("myApp", ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/angular', {
templateUrl: 'angular.php',
controller: 'dataCtr'
})
.when('/details', {
templateUrl: 'details.php',
controller: 'dataCtr'
})
.otherwise({
redirectTo: '/angular'
});
});
app.controller('dataCtr', function($scope ,$http ,$location ,$route ,$routeParams) {
$http({
method: "GET",
url: "json.php"})
.success(function (response) {$scope.names = response;});
$scope.changeView = function()
{
$location.url('/details');
};
$scope.disp = function(id)
{
$scope.stxt = $scope.names[id-1].Title;
};
});
The disp function is working fine on the angular view. But not being routed on the second view. I think the syntax for calling the two views in ng click is correct. OR if there any other method to call the associated table cell value to the second view. Please Help.
After a lots of research i figured it out.I used a factory service
app.factory('Scopes', function ($rootScope) {
var mem = {};
return {
store: function (key, value) {
$rootScope.$emit('scope.stored', key);
mem[key] = value;
},
get: function (key) {
return mem[key];
}
};
});
Added this to JS.
Because The scope gets lost on second Controller ,Services help us retain the scope value and use them in different controllers.Stored the scope from first controller
app.controller('dataCtr', function($scope ,$http ,$location,$rootScope,Scopes) {
Scopes.store('dataCtr', $scope);
//code
});
and loaded in the seconded controller.
app.controller('dataCtr2', function($scope ,$timeout,$rootScope,Scopes){
$scope.stxt = Scopes.get('dataCtr').disp;
});
Second view is not working because you cannot use $scope.$apply() method.
$apply() is used to execute an expression in angular from outside of the angular framework.$scope.$apply() right after you have changed the location Angular know that things have changed.
change following code part ,try again
$location.path('/detail');
$scope.$apply();

finish a controller treatment before execute another

i have 2 controller loaded in one page : one loaded by $routeProvider,
application.js
.when('/service/:serviceId/:serviceName/',
{
templateUrl : 'view/service/service.html',
controller : 'ServiceController'
})
the other loaded in the view
service.html
<div align="left">
<table class="table-flag">
<tr ng-controller="LanguageController">
<td ng-repeat="language in listLanguage"
width="50">
<input type="image" ng-src="img/flags/{{language.code}}.jpg"width="30" height="20"></input> </a>
</td>
</tr>
</table>
<div>
<br />
<ul>
<table class="table table-hover">
<tbody>
<tr
ng-repeat="detail in service.infoList">
<td><span ng-bind-html-unsafe="detail.label"></span></td>
</tr>
</tbody>
</table>
</ul>
</div>
</div>
I retrieve some datas from a server using rest
ServiceController
Info.controller('ServiceController', function ServiceController(
$scope, $http, $routeParams, manageDatas) {
$scope.serviceId = $routeParams.serviceId;
$scope.serviceName = $routeParams.serviceName ;
var paramsService = {
serviceId : $scope.serviceId,
serviceName : $scope.serviceName
};
$scope.loading = true;
var response = $http({
url : 'rest/service',
params : paramsService,
method : 'GET'
});
response.success(function(service) {
$scope.service = service;
$scope.loading = false;
manageDatas.setArrayData($scope.service.languageList); // service which allow to pass an array in LanguageController
});
});
LanguageController
LanguageController.controller('LanguageController', function ServiceByLanguageController(
$scope, $http, $routeParams, $timeout , manageDatas , $route) {
$scope.listLanguage = manageDatas.getDatas(); // retrieve the array passed in ServiceController by a service
// always null
});
The problem is the $http.success method in ServiceController is always executed AFTER LanguageController(verified by breakpoints) so the array $scope.listLanguage is always empty because i don t pass datas....
How can i make the languageController be executed after all the treatments in serviceController finish ?
Thank you very much
Alternatively, you can broadcast event in response.success(function(service) {...}, say, using $rootScope, and let LanguageController listen to this event and then do assignment $scope.listLanguage = ...
Just after a brief look, I would say that part or all of your ServicesController logic should be in a service and not a controller. You seem to have such a service in manageDatas. Just put all the code that actually loads and writes data to the service inside the service.

Resources