Disappearing/re-appearing JSON data - javascript

I'm using Angular, and have a JSON response where one of the property values is disappearing (is empty), but if you look at it directly, it appears (and has the proper values). The property that is supposed to have data is the vehicles property.
The JSON data
{
"data": {
"blocks": [
{
"vehicles": [
{
"agency": "ZGM Bike Share",
"mode": "bikeshare",
"name": "Research Chemistry Lab",
"space_count": 4
},
{
"agency": "ZGM Bike Share",
"mode": "bikeshare",
"name": "ENG North",
"space_count": 4
},
{
"agency": "ZGM Bike Share",
"mode": "bikeshare",
"name": "Research South",
"space_count": 6
}
]
}
],
"screen": {}
}
}
The console
Below are 2 console.log() from this. One is the full response, and the other is accessing the vehicles property directly. As you can see, in the full response, it is empty, but when accessed directly it contains data.
The problem
We are using Angular and after some JS manipulation, which happens after the console.log() above, we are passing this object to a template. Because it's being passed as a full object, it passes it with vehicles empty.
The code snippet
This is the part that makes the call and handles the response.
tsApp.service('updateService', function($http, $q, jsonResponse, $timeout, $interval, $log, $location) {
// Cut out a bunch of code that happens after getUpdate()
function getUpdate() {
var request = $http({
method: 'get',
dataType: 'json',
url: '/data/' + id + '.json',
timeout: updateRequestTimeout
});
return (request.then(handleSuccess, handleError));
}
function handleSuccess(response) {
console.log(response.data);
console.log(response.data.data.blocks[0].vehicles);
return response.data;
}
return updateService;
});

So I understand the following from your question:
You requested a resource from a remote server, got it, but the angular service returns nothing when its being called from a controller etc.
The problem is, that you initiated the request itself, and you returned the value of the handleSuccess function to the service itself, not to the caller of it.
Here's the fixed code:
tsApp.service('updateService', function($http, $q, jsonResponse, $timeout, $interval, $log, $location) {
var serviceObj = { vehicles: [] };
// Cut out a bunch of code that happens after getUpdate()
function getUpdate() {
var request = $http({
method: 'get',
dataType: 'json',
url: '/data/' + id + '.json',
timeout: updateRequestTimeout
});
request.then(handleSuccess, handleError);
}
function handleSuccess(response) {
console.log(response.data);
console.log(response.data.data.blocks[0].vehicles);
serviceObj.vehicles = response.data.data.blocks[0].vehicles;
}
return serviceObj;
});
Now, when you will need the vehicles object, you will call:
updateService.vehicles
Note that it will be empty until the response retrieved. To make sure you got it before you use it, you can also add a broadcast event on the rootScope. That way, the controller / directive that want to use it, will be able to determine if its already sent:
// Broadcast the handleSuccess event
serviceObj.ready = true;
$rootScope.$boradcast("updateService.vehicles.success", true);
// Listen to this event from other controller / directive to make sure the request finished up
if(updateService.ready === true) {
successFunc()
}
$rootScope.$on("updateService.vehicles.success", successFunc);

Related

AngularJS Two-way data binding canceled out by setTimeout

I've got this snippet of HTML using the Controller As syntax:
<div ng-class="{'hide': !autoDeploy.uiVisibility.overlayLoaderVisible, 'show': autoDeploy.uiVisibility.overlayLoaderVisible}" />
<div ng-class="{'animate-top hide': !autoDeploy.uiVisibility.resultVisible, 'animate-bottom show': autoDeploy.uiVisibility.resultVisible}">
<button ng-click="autoDeploy.btn_extractFormData()">click</button>
with this very stripped down controller:
angular.module("gms.autoDeploy").controller('AutoDeployController', ['$scope', 'AutoDeployService',
function ($scope, AutoDeployService) {
var model = this;
// two-way data binding model to view
model.uiVisibility = AutoDeployService.getUIVisibility();
// Pull the data from our data model arrays
function btn_extractFormData() {
AutoDeployService.extractFormData();
}
model.btn_extractFormData = btn_extractFormData;
}
]);
and this segment from my service module:
var uiVisibility = {
resultVisible: false,
overlayLoaderVisible: false
};
function getBuildResult() {
$http({
url: 'https://jenkins...com/job/...',
method: 'GET',
headers: {
'Accept': "*/*",
'Authorization': 'Basic ...'
}
})
.then(function (res) {
//stuff happens here
})
.catch(function (res) {
// stuff also happens here
});
setTimeout(function () {
uiVisibility.overlayLoaderVisible = false;
uiVisibility.resultVisible = true;
}, 1100);
}
// return this service (contains the objects that we want to be public)
return {
getUIVisibility: getUIVisibility,
extractFormData: extractFormData
};
}
My issue here is that when the values of uiVisibility.overlayLoaderVisible and uiVisibility.resultVisible are changed in the above setTimeout(), nothing happens on the UI but I know it executes because I've tested it with console logging. If I replace the timeout with just the two lines then they will execute, but it's synchronous, so there's a second or so between each being updated in the view.
My question: Is there some mechanism here preventing the two-way data binding when the value is modified in the async setTimeout() method?
I put the two values into an associative array to account for JavaScript's pass-by-sharing, and works fine with all other objects that I use two-way binding on.
Inject the $timeout service into your service, and use that instead. It will trigger a digest for you:
$timeout(function () {
uiVisibility.overlayLoaderVisible = false;
uiVisibility.resultVisible = true;
}, 1100);

AngularJS communication between components through a template (with a promise)

I'm working on an app that has actor listings. There are tags and actors with a many to many relationships on the backend.
I have 2 components and I want to pass and unresolved promise between them through a template.
This is the actor-tag-detail component:
angular.module('actorTagDetail').component('actorTagDetail', {
templateUrl: 'static/partials/actor-tag-detail/actor-tag-detail.template.html',
controller: ['$routeParams', 'ActorTag',
function ActorTagDetailController($routeParams, ActorTag) {
var self = this;
self.actorTag = ActorTag.get({actorTagId: $routeParams.actorTagId})
}
]
});
The actorTag returns a JSON for the ActorTag object from the backend that looks like this:
{
"id": 37,
"name": "Oscar Winner",
"actors": [
664,
668,
670,
673,
678,
696
] }
I also have an actor-list component that is responsible for retrieving an actor list from the backend:
angular.module('actorList').component('actorList', {
templateUrl: 'static/partials/actor-list/actor-list.template.html',
bindings: {
pk: '='
},
controller: ['Actor',
function ActorListController(Actor) {
var self = this;
alert(self.pk)
self.actors = Actor.query();
self.orderProp = 'name';
}
]
});
In the template for actor-tag-details I'm trying to pass an attribute to the actor-list component.
actor-tag-detail.template.html:
<actor-list pk="$ctrl.actorTag.actors"></actor-list>
What I'm trying to achieve is to have access to the retrieved JSON data in the actor-list component. However I'm getting an 'unresolved object error' instead of the desired result when I try to alert(self.pk) in actor-list.component.This is happening because when alert(self.pk) runs, the data is not yet retrieved from the backend.
I do not know how to remedy the situation.
Is there a way to specify in the receiving component to await execution until the promise is resolved and the data received from the backend?
Or, am I'm doing it completely wrong and there is a better way to pass this information between components?
Use a watcher to listen the object changes:
function ActorListController($scope, Actor) {
var self = this;
$scope.$watch(function() {
return self.pk;
}, function(newValue, oldValue) {
if(angular.isObject(newValue) {
//alert(self.pk)
self.actors = Actor.query();
}
}
}

How should i use ngResource with a specific response body?

My response body looks like this:
{
"code": 200,
"message": Items succesfully retrieved,
"items": [
{
...
}
]
}
I was using $http before so i didn't have this problem but i've decided to switch to ngResource because it seemed better. And i'm sure i'm doing it wrong, so if you could please tell me how to target 'items' (in this example) to be the returned object (same for put, post, ...)
Here is the sample of code i've made to try out ngResource
app.factory("Product", function($resource,APILINK) {
return $resource(APILINK+"/api/v1/products/:id", {id: '#id'}, {
query: {method: 'GET',
isArray: false
},
update: { method: 'PUT' }
});
});
I don't really know if it's a good way to build my REST Api sending the code and message. But it feels much cleaner this way :'(
Do I need to modify the json sent by my REST Api ? Or is there a way to make ngResource ignore "code" and "message" in the response body ?
Setting the status code and message in your data transfer (json) object might not be the way to go. Is it necessary to access the status code?
The documentation on $resource reads as follows:
HTTP GET "class" actions: Resource.action([parameters], [success],
[error])
non-GET "class" actions: Resource.action([parameters],
postData, [success], [error])
non-GET instance actions:
instance.$action([parameters], [success], [error])
So, every $resource call gives us a success and error callback.
For example:
var Product = $resource('/api/as/product');
Product.query(function(items) {
// success handler
}, function(error) {
// error handler
});
You might not be able to read the status code, but you have knowledge about whether or not your call was successful.
Alternatively, you can look into interceptors if getting the status code is a must:
// Resource
var Product = $resource(url, {}, {
get: {
method: 'GET'
interceptor: {
response: function(response) {
var result = response.resource;
result.$status = response.status;
return result;
}
}
}
});
// Caller
Product.get(params, function(result) {
console.log('status code: ' + result.$status);
});
When a call is made with this resource, we will intercept the result, add the status code to it from the response and then return it to the caller.
When you reference your get and put and other REST verbs, you can specify the items object.
GET Example:
var itemList = Product.query({ id: 12345 }).items;
PUT Example:
var MyItemList = {
"code": 200,
"message": "Items succesfully retrieved",
"items": [ { ... }, { ... }, { ... } ]
}
Product.update({ id: 12345 }, MyItemList.items);
Although if you're just sending itemList from the first example, you already have it narrowed down to just the items[] array which won't include the code and message.

How do you search and return a specific index of a JSON resource in AngularJS?

I have a json file of events setup like this:
{
2: {
sched_conf_id: "38",
title: "Coffee Break",
},
3: {
sched_conf_id: "39",
title: "registration",
},
}
I setup and angular factory like this:
.factory('eventFactory', ['$resource',
function($resource) {
return {
query: function(event_id) {
return $resource('/assets/events.json', {}, {
query: { method: 'GET', params: {id:event_id}, isArray: false }
}).query();
}
}
}
])
and lastly I have my angular controller which calls the query method from the factory with the id being the id from the url:
.controller('eventCtrl', function($scope, $routeParams, eventFactory) {
var eventId = $routeParams.event_id;
$scope.eventData = eventFactory.query(eventId);
})
The return data seems to be just the entire events.json file rather than just the specific id I want to query for in the parameters. In the params I am trying id but that is obviously not correct. Using this setup how can I return just the data from event_id: 2?
Assuming your production scheme is going to be fetching just a static file that doesn't do anything with arguments passed in, you need to extract the record you need after it's returned from the server.
Basically, you're requesting something like http://yourhost.com/assets/events.json?event_id=3 and if it's just a static file, the server can't do anything with that parameter. In practice, I would think you'd actually be requesting a response from a web service that can handle that, in which case your client-side code would probably work as-is.
In this specific case, however, I would think that you could handle this with an interceptor. Something like this:
.factory('eventFactory', ['$resource',
function($resource) {
return {
query: function(event_id) {
return $resource('/assets/events.json', {}, {
query: { method: 'GET', isArray: false,
interceptor: {response:
function(data){ var d = JSON.parse(data);
return d[event_id];
}
}
}
});
}
}
}
])
I don't have an environment set up to test this at the moment, but I think it should work. I have a couple places in my own code where I do something similar, for other reasons.

displaying Data from multiple tables with AngularJs

I have been reading different posts with similar questions but I cannot get this figured out. I have a Job class that is linked to different tables such as Customer and Employee. The Data is coming back from the Database but I cannot get the Angular Table to display the linked classes. The suggestions have been to use different mods, restangular, angular-activerecord, ModelCore and this method
angular js model relationships
I am not sure the best route to take and what would be the simplest way of doing it.
app.factory('Job', function ($resource) {
return $resource('/api/apiJob/:id',
{ id: '#id' },
{ 'save': { method: 'POST' } },
{ 'update': { method: 'PUT' } },
{ 'query': { method: 'GET', isArray: false } });
});
app.factory('jobFactory', function ($http) {
return {
updateJob: function (job) {
return $http.put('/api/apiJob/' + job.JobId, job);
}
};
});
app.factory('Customer', function ($resource) {
return $resource('/api/apiCustomer/:id',
{ id: '#id' },
{ 'save': { method: 'POST' } },
{ 'update': { method: 'PUT' } },
{ 'query': { method: 'GET', isArray: false } });
});
app.factory('customerFactory', function ($http) {
return {
updateCustomer: function (customer) {
return $http.put('/api/apiCustomer/' + customer.CustomerId, customer);
}
};
});
'use strict';
app.controller('JobCtrl', function ($scope, Job, $resource, $route, jobFactory, notificationFactory, $http) {
////GET Jobs
$scope.jobArray = Job.query()
//New Job Modal
$scope.NewJobModal = function () {
$('#NewJobModal').modal();
}
$scope.submitJob = function () {
var data = {
JobId: $scope.JobId,
JobNumber: $scope.JobNumber,
JobName: $scope.JobName,
CustomerName: $scope.CustomerName,
JobDescription: $scope.JobDescription,
OriginalContract: $scope.OriginalContract,
BillingDate: $scope.BillingDate,
}
$http.post('/api/apiJob/PostNewJob', data).success(function (data, status, headers) {
console.log(data);
});
window.top.location.reload();
};
//End New Job Post
//Delete Job
$scope.deleteJob = function (job) {
Job.delete({ id: job.JobId }, function () {
if ($scope.jobArray.length === 1) {
$scope.jobArray.splice(-1, 2);
} else {
$scope.jobArray.splice(job.JobId - 1, 2);
}
window.top.location.reload();
});
};
//End Delete Job
$scope.updateJob = function (job) {
jobFactory.updateJob(job).success(successCallback).error(errorCallback);
};
$scope.job = [];
var successCallback = function (data, status, headers, config) {
notificationFactory.success();
return $('#editJobModal').modal('hide');
};
var errorCallback = function (data, status, headers, config) {
notificationFactory.error(data.ExceptionMessage);
};
//End Edit Job
}); //End Job Controller
What It looks like in the Browser Console
0: {$id:1, JobId:1, JobNumber:2534, JobName:St.Lukes, JobDescription:Rebuilding Cafeteria,…}
$id: "1"
BalanceDue: 89654123
BalanceToBill: 541256
BillingDate: "2014-08-12T14:43:22.507"
BillingForm: "Invoice"
Budget: 854523658
CertPayroll: true
ChangeOrders: [{$id:4, ChangeOrderId:1, ChangeOrderNumber:7854, ChangeOrderDate:2014-08-12T14:43:22.673,…}]
ContractDate: "2014-08-12T14:43:22.507"
Customers: [{$id:2, CustomerId:2, CustomerName:Grove at Wilcrest, CustomerPhoneNumber:8327899667,…}]
0: {$id:2, CustomerId:2, CustomerName:Grove at Wilcrest, CustomerPhoneNumber:8327899667,…}
Employees: [{$id:3, EmployeeId:2, AccountName:Ham Sandwich, EmployeeFirstName:Scott, EmployeeLastName:Willis,…}]
JobAddress: "1234 Mason Rd"
JobCity: "Katy"
JobCost: 784556124
Updated Factory
app.factory('JobGet', function ($http, $q) {
var data = $http({
method: 'GET',
url: '/api/apiJob'
})
return {
query: function () {
var deferred = $q.defer();
setTimeout(function () {
deferred.resolve(data)
}, 2000);
return deferred.promise;
}
};
});
Network Response Tab
[{"$id":"1","JobId":1,"JobNumber":2534,"JobName":"St.Lukes","JobDescription":"Rebuilding Cafeteria","OriginalContract":1250210,"ContractDate":"2014-08-12T14:43:22.507","BillingDate":"2014-08-12T14:43:22.507","TotalCO":12502105,"RevisedContract":452136852,"Budget":854523658,"BillingForm":"Invoice","TESPM":"Frank Harvel","TESSuperintendent":"Rudy Sanchez","Status":"Active","MoreShit":"More shit goes here","TaxExempt":true,"CertPayroll":true,"JobCost":784556124,"RemainingBudget":96523145,"Profit":854125,"Percentage":45,"TotalBilled":45236554,"BalanceToBill":541256,"PaidToDate":0,"BalanceDue":89654123,"JobAddress":"1234 Mason Rd","JobCity":"Katy","JobState":"TX","JobZipcode":77493,"JobCounty":"Harris","JobPhone":2814569654,"JobFax":2814563251,"JobHidden":false,"Customers":[{"$id":"2","CustomerId":2,"CustomerName":"Grove at Wilcrest","CustomerPhoneNumber":8327899667,"CustomerFaxNumber":7134568547,"CustomerAddress":"56328 Richmond Ave","CustomerCity":"Houston","CustomerState":"TX","CustomerZipcode":77042,"CustomerWebsite":"grovewilcrest.com","CustomerOtherShit":"Other Shit Goes here","CustomerHidden":false,"CustomerPM":null,"CustomerAdmin":"Jane Miller","CustomerAccountant":"Betsy Sue","TESSuperintendent":null,"JobId":1,"Job":{"$ref":"1"}}],"Employees":[{"$id":"3","EmployeeId":2,"AccountName":"Ham Sandwich","EmployeeFirstName":"Scott","EmployeeLastName":"Willis","EmployeeTitle":"Admin","EmployeeCellPhone":2818567854,"EmployeeOfficePhone":7134527854,"EmployeeEmail":"testing#gmail.com","CompanyEmployeeId":12521,"EmployeeHidden":false,"EmployeeIsSuper":true,"EmployeeIsPM":true,"JobId":1,"Job":{"$ref":"1"}}],"ChangeOrders":[{"$id":"4","ChangeOrderId":1,"ChangeOrderNumber":7854,"ChangeOrderDate":"2014-08-12T14:43:22.673","ChangeOrderName":"Insert Name Here","ChangeOrderDescription":"It changed","ChangeOrderAmount":4000,"ChangeOrderApprovedDate":"2014-08-12T14:43:22.673","ChangeOrderApprovedAmount":3000,"ChangeOrderApprovedNumber":1,"ChangeOrderAttn":"Frank Harvel","ChangeOrderHidden":false,"JobId":1,"Job":{"$ref":"1"}}]},{"$id":"5","JobId":2,"JobNumber":12343,"JobName":"Katy Mills","JobDescription":"New Mall Bathrooms","OriginalContract":32623212,"ContractDate":"2014-08-12T14:43:22.507","BillingDate":"2014-08-12T14:43:22.507","TotalCO":12502105,"RevisedContract":452136852,"Budget":854523658,"BillingForm":"Invoice","TESPM":"Frank Harvel","TESSuperintendent":"Mike Hall","Status":"Active","MoreShit":"More shit goes here","TaxExempt":true,"CertPayroll":true,"JobCost":784556124,"RemainingBudget":96523145,"Profit":854125,"Percentage":45,"TotalBilled":45236554,"BalanceToBill":541256,"PaidToDate":0,"BalanceDue":89654123,"JobAddress":"1234 Mason Rd","JobCity":"Katy","JobState":"TX","JobZipcode":77493,"JobCounty":"Harris","JobPhone":2814456965,"JobFax":2814563225,"JobHidden":false,"Customers":[{"$id":"6","CustomerId":1,"CustomerName":"City Center","CustomerPhoneNumber":8327899667,"CustomerFaxNumber":7134568547,"CustomerAddress":"123453 HWY 6","CustomerCity":"Katy","CustomerState":"TX","CustomerZipcode":77493,"CustomerWebsite":"citycenter.com","CustomerOtherShit":"Other Shit Goes here","CustomerHidden":false,"CustomerPM":null,"CustomerAdmin":"Jane Miller","CustomerAccountant":"Betsy Sue","TESSuperintendent":null,"JobId":2,"Job":{"$ref":"5"}}],"Employees":[{"$id":"7","EmployeeId":3,"AccountName":"Ice Cream","EmployeeFirstName":"Aaron","EmployeeLastName":"Horstmann","EmployeeTitle":"Office Bitch","EmployeeCellPhone":2818567854,"EmployeeOfficePhone":7134527854,"EmployeeEmail":"aaron#gmail.com","CompanyEmployeeId":12521,"EmployeeHidden":false,"EmployeeIsSuper":true,"EmployeeIsPM":true,"JobId":2,"Job":{"$ref":"5"}}],"ChangeOrders":[{"$id":"8","ChangeOrderId":2,"ChangeOrderNumber":1823,"ChangeOrderDate":"2014-08-12T14:43:22.673","ChangeOrderName":"Insert Name Here","ChangeOrderDescription":"Work Orders","ChangeOrderAmount":4000,"ChangeOrderApprovedDate":"2014-08-12T14:43:22.673","ChangeOrderApprovedAmount":3000,"ChangeOrderApprovedNumber":2,"ChangeOrderAttn":"Rosie Sanchez","ChangeOrderHidden":false,"JobId":2,"Job":{"$ref":"5"}}]},{"$id":"9","JobId":3,"JobNumber":12398,"JobName":"City Center","JobDescription":"Remodeling Yard House","OriginalContract":56325412,"ContractDate":"2014-08-12T14:43:22.507","BillingDate":"2014-08-12T14:43:22.507","TotalCO":12502105,"RevisedContract":452136852,"Budget":854523658,"BillingForm":"Invoice","TESPM":"Frank Harvel","TESSuperintendent":"Shawn Saulnier","Status":"Active","MoreShit":"More shit goes here","TaxExempt":true,"CertPayroll":true,"JobCost":784556124,"RemainingBudget":96523145,"Profit":854125,"Percentage":45,"TotalBilled":45236554,"BalanceToBill":541256,"PaidToDate":0,"BalanceDue":89654123,"JobAddress":"1234 Mason Rd","JobCity":"Katy","JobState":"TX","JobZipcode":77493,"JobCounty":"Harris","JobPhone":2814256965,"JobFax":2814565325,"JobHidden":false,"Customers":[{"$id":"10","CustomerId":3,"CustomerName":"Twin Peaks","CustomerPhoneNumber":8327899667,"CustomerFaxNumber":7134568547,"CustomerAddress":"8473 Katy Fwy","CustomerCity":"Houston","CustomerState":"TX","CustomerZipcode":77043,"CustomerWebsite":"citycenter.com","CustomerOtherShit":"Other Shit Goes here","CustomerHidden":false,"CustomerPM":null,"CustomerAdmin":"Jane Miller","CustomerAccountant":"Betsy Sue","TESSuperintendent":null,"JobId":3,"Job":{"$ref":"9"}}],"Employees":[{"$id":"11","EmployeeId":1,"AccountName":"Not Sure","EmployeeFirstName":"Frank","EmployeeLastName":"Harvel","EmployeeTitle":"Manager","EmployeeCellPhone":2818567854,"EmployeeOfficePhone":7134527854,"EmployeeEmail":"texas45#gmail.com","CompanyEmployeeId":12521,"EmployeeHidden":false,"EmployeeIsSuper":true,"EmployeeIsPM":false,"JobId":3,"Job":{"$ref":"9"}}],"ChangeOrders":[{"$id":"12","ChangeOrderId":3,"ChangeOrderNumber":45324,"ChangeOrderDate":"2014-08-12T14:43:22.673","ChangeOrderName":"Insert Name Here","ChangeOrderDescription":"It changed again","ChangeOrderAmount":4000,"ChangeOrderApprovedDate":"2014-08-12T14:43:22.673","ChangeOrderApprovedAmount":3000,"ChangeOrderApprovedNumber":3,"ChangeOrderAttn":"Travis Dillard","ChangeOrderHidden":false,"JobId":3,"Job":{"$ref":"9"}}]}]
First of all, this is a work in progress. Your code is very large and to solve this I removed a lot o noise from your plunkr, I left there only what's essential to make it work and only the code involved in it.
Working Demo
First thing to notice, on your JobController you are doing:
////GET Jobs
$scope.jobArray = Job.query();
This worked on previous versions of angular, on the current version there is no automatic promise unwrapping anymore, so you must use the then function:
////GET Jobs
Job.query().then(function(retrievedData){
$scope.jobArray = retrievedData;
});
Notice that on the plunkr I "mocked" the returning of data using $q and a timeout, I actually cleaned the json leaving only the properties that are used on the table, just to make it simpler, you don't need to do that on your code ok? Just keep that part as it is.
Maybe you'll have to modify it just to resolve the promise with the returned data, but this is up to you, the important thing is to return a promise from your query() method and resolve it.
On the HTML I noticed that you are binding the customer name like this:
<td>{{job.Customers.CustomerName}}</td>
But on your Json, the Customers property is an array of customers, so you either return one customer from your api or bind it like this:
<td>{{job.Customers[0].CustomerName}}</td>
I also noticed that there are a lot of jQuery references on your controllers like this:
$('#editJobModal').modal();
This is not recommended and I don't think it will work at all, when dealing with the DOM, always use directives and comunicate with them using bindings, thats the angular way.
Well after all this, my plunkr is showing the table with the 2 fake customers from the Json. Now I suggest you to study that code and apply those principles to your app.
I hope I could help or at least point you at the right direction.

Categories

Resources