I've tried different variations of $apply() and $digest() to no avail.
The binding should update once the courier is no longer null with the name of the courier, however nothing is happening. I've been able to log the name of the courier when they are assigned, however the dom element is not updating. I'm using jade and compiling to html without any issues elsewhere in the application. I'm also calling the refreshDelivery function immediately prior to rendering the view shown below, which is working correctly.
app.js:
var storeController = require('./controllers/controller');
var storeApp = angular.module('AngularStore', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/store', {
templateUrl: 'views/store.html',
controller: storeController }).
when('/products/:productSku', {
templateUrl: 'views/product.html',
controller: storeController }).
when('/cart', {
templateUrl: 'views/shoppingCart.html',
controller: storeController }).
when('/delivery', {
templateUrl: 'views/delivery.html',
controller: storeController }).
otherwise({
redirectTo: '/store' });
}])
.controller('storeController', storeController);
controller.js:
function storeController($scope, $routeParams, $http, $interval, DataService) {
// get store and cart from service
$scope.store = DataService.store;
$scope.cart = DataService.cart;
$scope.mapInit = DataService.mapInit;
// use routing to pick the selected product
if ($routeParams.productSku != null) {
$scope.product = $scope.store.getProduct($routeParams.productSku);
}
// var locationOptions = {
// enableHighAccuracy: true,
// timeout: 5000,
// maximumAge: 0
// }
// navigator.geolocation.getCurrentPosition(function(pos){
// var mapOptions = {
// center: { lat: pos.coords.latitude, lng: pos.coords.longitude},
// zoom: 13
// };
// var map = new google.maps.Map(document.getElementById('map'),
// mapOptions);
// });
$scope.search = function(query){
var responseObject;
console.log('in search');
$http({
url:'/apiCall',
data: {data: '/products?keyword=' + query + '&latlong=36.125962,-115.211263'},
method: 'POST'
})
.then(function(response){
responseObject = response.data.data;
responseObject.forEach(function(data){
var productData = {
sku: data.Id.SkuPartNumber,
productName: data.Description.Name,
desc: data.Description.BrandName,
price: data.Price.DisplayPrice,
url: data.Description.ImageURL,
storeNumber: data.StoreNumber
}
var temp = new product(productData)
$scope.store.addProduct(temp)
});
});
}
$scope.getDeliveryQuote = function(){
var responseObject;
$scope.quoted = false;
var storeNumber = $scope.cart.items[0].storeNumber
console.log($scope.cart.items[0].storeNumber);
var url = '/delivery_quote?drop_off_latlong=36.125962,-115.211263&pickup_store_number='.concat(storeNumber);
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(response){
$scope.quoted = true;
console.log(response.data.id);
$scope.quote = response.data.fee;
$scope.quoteId = response.data.id
})
}
$scope.submitOrder = function(){
var url = '/submit_delivery?drop_off_latlong=36.125962,-115.211263&pickup_store_number=0001709&manifest=puppies&phone_number=555-555-5555"e_id=' + $scope.quoteId + '&customer_name=Arnold';
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(response){
console.log(response);
$scope.deliveryId = response.data.id;
$scope.refreshDelivery();
window.location.href='/#/delivery';
})
}
$scope.refreshDelivery = function() {
var url = '/update?delivery_id='.concat($scope.deliveryId);
var promise = $interval(function(){
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(resp) {
$scope.update = resp.data;
if (resp.data.courier){
$scope.update.courier = resp.data.courier;
console.log($scope.update.courier.name);//outputs correct name
$scope.$apply();
}
//stops when complete
if ($scope.update.complete){
$interval.cancel(promise);
}
})
}, 5000 );
}
}
module.exports = storeController;
Jade before compiling to HTML:
Partial:
p.text-info {{update.courier.name}} is on their way!
Default:
html(ng-app='AngularStore')
head
// includes for jquery, angular, and bootstrap
script(src="https://maps.googleapis.com/maps/api/js?sensor=false")
script(src='bower_components/jquery/dist/jquery.min.js')
script(rel='stylesheet' href='bower_components/bootstrap/dist/css/bootstrap.min.css')
script(src='bower_components/angular/angular.js')
script(src='bower_components/angular-route/angular-route.js')
// includes for the Angular Store app
script(src='/js/main.js')
script(src='/js/bundle.js')
link(href='/styles/main.css', rel='stylesheet', type='text/css')
|
body
.container-fluid
.row-fluid
.span10.offset1
h1.well
a(href='default.html')
| Angular Store
div(ng-view='')
I found a way around the $scope issue by creating a separate controller to handle updates.
app:
var storeController = require('./controllers/storeController'),
deliveryController = require('./controllers/deliveryController');
var storeApp = angular.module('AngularStore', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/store', {
templateUrl: 'views/store.html',
controller: storeController }).
when('/products/:productSku', {
templateUrl: 'views/product.html',
controller: storeController }).
when('/cart', {
templateUrl: 'views/shoppingCart.html',
controller: storeController }).
when('/delivery/:id', {
templateUrl: 'views/delivery.html',
controller: deliveryController }).
otherwise({
redirectTo: '/store' });
}])
.controller('storeController', storeController);
new deliveryController
function deliveryController($scope, $routeParams, $http, $interval) {
console.log($routeParams);
var refreshDelivery = function(id) {
var url = '/update?delivery_id='.concat(id);
var promise = $interval(function(){
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(resp) {
$scope.update = resp.data;
if (resp.data.courier){
$scope.update.courier = resp.data.courier;
console.log($scope.update.courier.name);//outputs correct name
}
//stops when complete
if ($scope.update.complete){
$interval.cancel(promise);
}
})
}, 5000 );
}
refreshDelivery($routeParams.id);
}
module.exports = deliveryController;
Related
I have 2 modules that should be connected.
The main module, called mainPage has the second module, called router, injected. They are in separate files. I want to use my service called userPropagatorService in mainPage and in router.
This service should be used to get and set currently logged in user.
I tried to inject service to router module, but I get errors.
How can I achieve this?
mainPage file:
var app = angular.module('mainPage',['reg','router']);
//Returns a promise which generates our user.
app.factory('userLoginService',['$http',function ($http){
return{
loginService: function(username,password){
var info = {username:username, password:password}
var user={};
//Returning http request because of promises
return $http({
url: 'webapi/users/login',
method: 'POST',
data: info,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data:{username: info.username, password: info.password}
}).then(function (response)
{
user = response.data
return user;
});
}
}
}]);
app.service('userPropagatorService', function(){
return{
get:function(){
return this.u;
},
set:function(user){
this.u = user;
}
}
});
router file:
var r = angular.module('router',['ngRoute'])
.config(['$routeProvider', '$locationProvider','userPropagatorService',
function($routeProvider, $locationProvider, userPropagatorService) {
$locationProvider.html5Mode(true);
$routeProvider
.when("/home",{
templateUrl: "pages/MainPage.html",
controller:"homeController"
})
.when("/forums",{
templateUrl: "pages/forumsPage.html",
controller:"forumController"
})
.when("/topics",{
templateUrl: "pages/topicsPage.html",
controller:"topicsController"
})
.when("/comments",{
templateUrl: "pages/commentsPage.html",
controller:"commentsController"
})
.otherwise({
redirectTo:"/home"
});
}])
.controller("homeController",['$scope','$http',function($scope,$http){
/*$http({
url: "webapi/forums/all",
method:"GET"
})
.then(function(response){
console.log("YEA!");
console.log(response.data);
},
function(response){
console.log("NO:(");
})*/
$scope.username = "visitor!"
$scope.user = userPropagatorService.get();
if($scope.user != null){
$scope.username=$scope.user.username + "!";
}
}])
.controller("forumController",['$scope','$http',function($scope,$http){
$scope.username = "visitor!"
}])
.controller("commentsController",['$scope','$http',function($scope,$http){
$scope.username = "visitor!"
}]);
If you want to use the userLoginService in the router module, it needs to be broken out of the main app.
var app = angular.module('mainPage',['reg','router']);
angular.module("services",[])
.factory('userLoginService',['$http',function ($http){
return{
//Service code here
};
}]);
Then add it as a dependency in the router module:
var r = angular.module('router',['ngRoute','services'])
You cant inject Service "userPropagatorService" in config block.
Make it a provider with $method and return function from there .
ang.provider('userPropagatorService', function(){
return{
get:function(){
console.log("in get");
},
set:function(user){
},
$get: function(){
return {
meth1: function(){
}
}
}
}
});
ang.config(function(userPropagatorServiceProvider){
console.log(userPropagatorServiceProvider.meth1())
})
This is my app.js
angular.module('app', ['ui.router', 'satellizer'])
.constant('API_URL', 'http://localhost/angular/public/api/v1/')
.config(function($stateProvider, $urlRouterProvider, $authProvider) {
$authProvider.loginUrl = 'angular/public/api/authenticate';
$urlRouterProvider.otherwise('/auth');
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: 'app/view/login.html',
controller: 'AuthController as auth'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: 'app/view/dashboard.tmpl.html',
params: {
model: ''
}
})
.state('dashboard.employees', {
templateUrl: 'app/view/employee.tmpl.html',
controller: 'employeesController',
}).state('dashboard.test', {
templateUrl: 'app/view/edit.tmpl.html',
controller: 'employeesController',
})
});
When I click ui-sref="dashboard.employees" controller calls twice.
calls twice
This is my controller which I want to use for all views. I developed cms on laravel and angular. I can't create a new controller for every table entity.
angular.module('app')
.controller('employeesController', function($scope, $http, API_URL,$stateParams) {
//retrieve employees listing from API
$scope.employees = '';
$http.get(API_URL + $stateParams.model)
.success(function(response) {
$scope.employees = response;
});
//show modal form
$scope.toggle = function(modalstate, id) {
$scope.modalstate = modalstate;
switch (modalstate) {
case 'add':
$scope.form_title = "Add New Employee";
break;
case 'edit':
$scope.form_title = "Employee Detail";
$scope.id = id;
$http.get(API_URL + $stateParams.model+'/' + id)
.success(function(response) {
console.log(response);
$scope.employee = response;
});
break;
default:
break;
}
$('#myModal').modal('show');
}
//save new record / update existing record
$scope.save = function(modalstate, id) {
var url = API_URL + "employees";
//append employee id to the URL if the form is in edit mode
if (modalstate === 'edit') {
url += "/" + id;
}
console.log('saved');
$http({
method: 'POST',
url: url,
data: $.param($scope.employee),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(response) {
var index = _.findIndex($scope.employees, function(b) {
return b.id == $scope.employee.id;
});
console.log(index);
if (index != -1) {
$scope.employees[index] = $scope.employee;
} else {
console.log($scope.employee);
$scope.employee.id = response;
$scope.employees.push($scope.employee);
console.log($scope.employees);
}
$('#myModal').modal('toggle');
}).error(function(response) {
console.log(response);
alert('This is embarassing. An error has occured. Please check the log for details');
});
}
//delete record
$scope.confirmDelete = function(employee) {
var isConfirmDelete = confirm('Are you sure you want this record?');
if (isConfirmDelete) {
$http({
method: 'DELETE',
url: API_URL + 'employees/' + employee.id
}).
success(function(data) {
_.remove($scope.employees, function(n) {
return n.id == employee.id;
});
console.log(data);
}).
error(function(data) {
console.log(data);
alert('Unable to delete');
});
} else {
return false;
}
}
});
Where is my mistake? How can I fix that?
kindly check, if you are called the controller in your employee.tmpl.html page, like ng-controller="employeesController"
Please remove it, if you call the ng-controller in your html
i created this site using django rest framework so that it works without refreshing the page at all,
http://192.241.153.25:8000/#/post/image3
and using angular js's route function was great choice of building a single page app.
but for some reason, the comment box doesn't seem to work possibly because it is put inside the angular js's template.
it throws me csrf token missing error even though the token is included.
judging by the fact that {% csrf token %} tag is visible as a text makes me think that the angular template cannot read the django tag.
could anyone tell me why the comment form isn't functioning and how i can fix this?
(function() {
angular.module('app', ['ngRoute', 'ngResource'])
.controller('FilesListCtrl', ['$scope','$http', function($scope, $http) {//this one controller is new
angular.forEach($scope.posts, function(_post){
$scope.styles = producePostStyle(_post)
});
function producePostStyle(post) {
return { "background-image": "url(" + post.image + ")" }
}
$scope.producePostStyle = producePostStyle;
$http.get('/api/posts/').then(function (response) {
$scope.viewStyle = {
background: 'url('+response.data.results.image+')'
};
});
$scope.images = [];
$scope.next_page = null;
var in_progress = true;
$scope.loadImages = function() {
//alert(in_progress);
if (in_progress){
var url = '/api/posts/';//api url
if ($scope.next_page) {
url = $scope.next_page;
}
$http.get(url).success(function(data) {
$scope.posts = $scope.posts.concat(data.results);//according to api
$scope.next_page = data.next;//acccording to api
if ( ( $scope.next_page == null ) || (!$scope.next_page) ) {
in_progress = false;
}
});
}
};
$scope.loadImages();
}])
angular.module('app')
.controller('profile_image', ['$scope','$http', function($scope, $http) {//this one controller is new
$http({
url: '/api/users/profile/',
method: "GET",
params: {username: 'lifeto'}
}).then(function successCallback(response) {
console.log("Profile Image");
console.log(response);
$scope.lifeto_img = response.data;
}, function errorCallback(response) {
console.log("Error fetching profile image!");
});
}])
.directive('whenScrolled', function($document) {//another directive
return function(scope, elm, attr) {
var raw = elm[0];
$document.bind('scroll', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.$apply(attr.whenScrolled);
}
});
};
})
.config(function($resourceProvider, $routeProvider, $httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
// Don't strip trailing slashes from calculated URLs
$resourceProvider.defaults.stripTrailingSlashes = false;
$routeProvider
.when('/', {
template: '<posts></posts>'
})
.when('/posts', {
template: '<posts></posts>'
})
.when('/post/:postId', {
template: '<post></post>'
})
.otherwise({
redirectTo: '/'
});
});
angular.module('app')
.constant('API_URL', '/api/posts/');
angular.module('app')
.factory('Posts', function($resource, API_URL) {
return $resource(API_URL, {format: 'json'}, {
queryPosts: {
method: 'GET',
isArray: false
},
getPostInfo: {
url: API_URL + ':postId/',
method: 'GET',
isArray: false,
params: {
postId: '#postId',
format: 'json'
}
}
});
});
angular.module('app')
.directive('post', function() {
return {
restrict: 'E',
templateUrl: '/static/post.html',
scope: {},
controller: function($scope, $routeParams, Posts) {
$scope.post = null;
function clean(id) {
return id.toLowerCase().replace(/\s/g, "-");
}
function _initialize() {
Posts.getPostInfo({
postId: clean($routeParams.postId)
})
.$promise
.then(function(result) {
$scope.post = result;
console.log(result)
});
}
_initialize();
}
};
});
angular.module('app')
.directive('posts', function() {
return {
restrict: 'E',
templateUrl: '/static/posts.html',
scope: {},
controller: function($scope, Posts) {
$scope.posts = [];
function _initialize() {
Posts.queryPosts().$promise.then(function(result) {
$scope.posts = result.results;
});
}
_initialize();
}
};
});
})();
Since you added
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$http will take care of csrf.
Now you can post data using $http
$http({
method: 'POST',
url: '/url/',
data: {
"key1": 'value1',
},
}).then(function successCallback(response) {
#do
},
function errorCallback(response) {
#do
});
Note: Dont use Ajax Post here. For that you have to do some csrf things other than this.
I have an usual AngularJS Controller:
controllers.UController = function ($scope, uFactory) {
$scope.data1 = uFactory.getDataUsingAjax1();
$scope.data2 = uFactory.getDataUsingAjax2();
$scope.data3 = uFactory.getDataUsingAjax3();
...
}
The mentioned fields (data1 - data3) gets populated using Ajax call.
I also have several Views.
When I run my app the first time, I can see all the 3 Ajax calls in order to populate data1-data3.
But every time I redirect to another View, I can see that this population starts again and again.
In my understanding it's not really a SPA architecture or it's a bad SPA.
Is this how it should work or I am missing something?
Here are the details:
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'UController',
templateUrl: '/Partial/View1.html'
})
.when('/View2',
{
controller: 'UController',
templateUrl: '/Partial/View2.html'
})
.otherwise({ redirectTo: '/View3' });
}]);
myApp.factory('uFactory', function () {
var factory = {};
data1 = [];
data2 = [];
factory.getAjaxData1 = function () {
$.ajax({
url: url,
type: 'GET',
contentType: "application/json",
async: false,
success: function (result) {
data1= result;
}
});
return data1;
}
factory.getAjaxData2 = function () {
$.ajax({
url: url,
type: 'GET',
contentType: "application/json",
async: false,
success: function (result) {
data2= result;
}
});
return data2;
}
}
var controllers = {};
controllers.uController = function ($scope, $location, uFactory) {
$scope.data1 = uFactory.getAjaxData1();
$scope.data2 = uFactory.getAjaxData2();
}
Redirection is done by href link:
a href="#/View1"Do it/a
My problem is that I have a $scope.page on to different controllers under the same module.
the $scope.page data should change for each route.
I'm trying to understand this...
some code:
hall.config(function ($routeProvider) {
$routeProvider.when("/", { controller: 'pageForsideController', templateUrl: "pages/forside.html" })
.when("/om", { controller: 'pageOmController', templateUrl: "pages/omMig.html" })
.otherwise({ redirectTo: '/' })
});
hall.controller('pageOmController', function ($scope, siteData) {
siteData.getServices(function (data) {
$scope.services = data;
})
siteData.getPageByName("Mig", function (data) {
$scope.page = data;
});
});
hall.controller('pageForsideController', function ($scope, siteData) {
siteData.getPageByName("Forside", function (data) {
$scope.page = data;
});
});
hall.factory("siteData", function ($http) {
return {
getServices: function (successcb) {
$http({ method: 'GET', url: 'data.json' })
.success(function (data, status, headers, confic) {
successcb(data.services);
console.log("getServices")
});
},
getPageByName: function (name, successcb) {
$http({ method: 'GET', url: 'data.json' })
.success(function (data, status, headers, confic) {
for (var i = 0; i < data.pages.length; i++)
if (data.pages[i].title == name)
successcb(data.pages[i]);
});
}
}
});
Updated:
here is a plunker
http://plnkr.co/edit/9K3C3ahi5WMPeKLeL318?p=preview
The OP fixed the problem by following charlieftl's instructions, and removing the controller from either markup or $routeProvider.