Explaining the problem:
So in the current app we have a couple of constant configuration declarations that connects the app to either the production or development environment, and we comment one out whenever we want to switch which doesn't seem like the ideal scenario to me. So what I was after is having a configuration external json file that contains the values and have that file separately from the changing code and get values from there into my constant.
The actual question:
In this piece of code:
application.constant('servicesConfig', (function() {
var con = 'appdev';
//var con = 'appprod';
return {
host: con+'.appdomain.com'
}
}
As you can see I have to modify the 'con' variable manually in order to switch between the dev and prod environments, instead, I want to do the following:
application.constant('servicesConfig', (function() {
var deferred = $q.defer();
var configLocation = 'config/server.json';
var configurations = $http.get(configLocation)
return {
host: configurations.con+'.appdomain.com'
}
}
My question is how can I get the $http or other angular services injected?
You can manually bootstrap angular after receive data from server.
Example on jsfiddle:
var app = angular.module("myApp", []);
app.controller("myController", function($scope, servicesConfig) {
console.log(servicesConfig);
$scope.model = servicesConfig.host;
$scope.reset = function() {
$scope.model = '';
};
});
angular.element(document).ready(function() {
//Simulate AJAX call to server
setTimeout(function() {
app.constant('servicesConfig', {
host: "appdev"
});
angular.bootstrap(document, ['myApp']);
}, 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-cloak>
<div ng-controller="myController">
<input type="text" ng-model="model" /> {{model}}
<button ng-click="reset()">Reset</button>
</div>
</div>
Related
I am using ngStomp to wire websocket subscriptions to angularjs controllers. When I have one controller on a page by itself it works fine. When I add another controller in an earlier div it stops working.
Is this because it's trying to connect stomp twice to the same endpoint?
My controller declarations are:
var market = 'all';
var orderApp = angular.module('openOrderApp', ['ngStomp']);
orderApp.controller('openOrderController', function ($stomp, $scope) {
$stomp.connect('https://localhost/marketdata-websocket', {})
.then(function (frame) {
console.log('Subscribing to /topic/openOrders');
var subscription = $stomp.subscribe('/topic/openOrders',
function (payload, headers, res) {
$scope.exchanges = payload;
$scope.$apply($scope.orders);
});
$stomp.send("/app/openOrders", market);
});
});
and
var market = 'all';
var statusApp = angular.module('statusApp', ['ngStomp']);
statusApp.controller('statusController', function ($stomp, $scope) {
$stomp.connect('https://localhost/marketdata-websocket', {})
.then(function (frame) {
console.log('Subscribing to /topic/exchangeStatus');
var subscription = $stomp.subscribe('/topic/exchangeStatus',
function (payload, headers, res) {
$scope.exchanges = payload;
$scope.$apply($scope.exchanges);
});
$stomp.send("/app/exchangeStatus", market);
});
});
and in one div there is:
<div class="openOrders row" ng-app="openOrderApp" ng-controller="openOrderController">
followed by:
<div class="exchangeStatus row" ng-app="statusApp" ng-controller="statusController">
When I remove the open orders div the status controller works ok.
After reading the angularjs docs rather than carrying on winging it :P
Cannot have two ng-apps declared on a page. Can obviously have multiple controllers. There's obviously many ways to structure this but I ended up by applying the two controllers to a module.
var app = angular.module('app', ['ngStomp']);
var controllers = {};
controllers.OpenOrderController = function ($stomp, $scope) {
console.log("Creating order controller");
etc...
};
controllers.ExchangeController = function ($stomp, $scope) {
console.log("Creating exchange controller");
etc...
};
app.controller(controllers);
And then in the html tag
<html ng-app>
And the controllers in the divs:
<div ng-controller="OpenOrderController">
<div ng-controller="ExchangeController">
There's a nice project for using Angular with WinJS controls together here: https://github.com/winjs/angular-winjs. I already have this working nicely in my app. However it doesn't really cover the use of angular for other parts of WinJS.
I am devloping on a windows 10 phone, and I have code like this:
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
How can I modify my app.onactivated assigment to do things the angular way so I can use $providers and modify $scope variables and so on?
By $providers do you mean the services that angular offers(like $http,$location and so on)?
If so, you can put onactivated method inside the controller callback Definition function(see below codes) so that it can use the angular services.
JS:
(function () {
"use strict";
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var myApp = angular.module("myApp", ["winjs"]);
var myController = myApp.controller("myController", function ($scope) {
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
$scope.$apply(function () {
$scope.test = "The Scope.test has been changed!";
});
}
args.setPromise(WinJS.UI.processAll());
}
};
});
app.start();
})(angular);
HTML:
<body class="win-type-body" ng-app="myApp">
<div ng-controller="myController">
<input type="text" ng-model="test"/>
{{test}}
</div>
If not so, can you tell me what $providers are?
I am trying to consume my ASP.NET Web API using AngularJs. The problem is that i want to pass optional parameters to the url based on the user input(2 Html Text Boxes) but i don't know how.
This is my ASP.NET Web API Controller
[Route("api/JobShow/{keyword}/{location}")]
public class JobShowController : ApiController
{
[HttpGet]
public PageResult<sp_JobSearch_Result> Get(ODataQueryOptions<sp_JobSearch_Result> options, string keyword = null, string location = null)
{
ODataQuerySettings settings = new ODataQuerySettings()
{
PageSize = 20
};
JobWindow obj = new JobWindow();
IQueryable results = options.ApplyTo(obj.showJobs(keyword, location).AsQueryable(), settings);
return new PageResult<sp_JobSearch_Result>(
results as IEnumerable<sp_JobSearch_Result>,
Request.GetNextPageLink(),
Request.GetInlineCount());
}
}
And this is my AngularJS controller
angular.module('JobSearch.SiteController', []).controller('JobSearchCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('/api/JobShow').success(function (data) {
$scope.model = data;
});
}]);
Example of the url then would be .../api/JobShow/Java/Toronto. Thank you all.
You can try ngResource !
You first need to include ng-resource
<script src="angular.js">
<script src="angular-resource.js">
You can get it via Bower or CDN, or whichever way you got AngularJS.
HTML:
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
<label>Keyword: <input type="text" ng-model="keyword" /></label>
<label>Location: <input type="text" ng-model="location" /></label>
<button ng-click="getJobShowPage(keyword, location)">Search</button>
</div>
</body>
Controller:
angular
.module('MyApp', ['ngResource']) // Include the ngResource module here
.controller('MyCtrl', ['$scope', '$resource', function($scope, $resource){
// Create the $resource
var JobShowPage = $resource('/api/JobShow/:keyword/:location', {keyword: "#keyword", location: "#location"})
// Make a scope function to use the resource properly
$scope.getJobShowPage = function(keyword, location) {
var parameters = {};
if (keyword) {
parameters["keyword"] = keyword;
if (location) {
parameters["location"] = location;
}
}
return JobShowPage.get(parameters);
};
}]);
Input/Outputs:
When the user enters nothing and clicks 'Search', the HTTP request would be /api/JobShow
If only the keyword is entered, the HTTP request would be /api/JobShow/{{keyword}}
If both the keyword and location is entered, the HTTP request would be /api/JobShow/{{keyword}}/{{location}}
If only the location is entered (no keyword), the HTTP request would be the vanilla one /api/JobShow
You can consume the return value of the $resource query like a promise:
JobShowPage.get(parameters).$promise.then(function(response){
// Do Stuff
$scope.model = response.data;
});
by callbacks:
JobShowPage.get(parameters, function(err, response){
// Do Stuff
$scope.model = response.data;
});
Or auto unwrap it:
// This works, but it's asynchronous
// Useful if consuming directly from the Angular Template
$scope.model = JobShowPage.get(parameters);
Based on your code, I'm going to assume you have 2 textboxes and a search button, and when the search button is pressed, you want to call your GET endpoint. For this scenario, what you'll want to do is bind the textbox inputs to your scope and bind the search button using ng-click to a function in your scope that will call your endpoint. It might look something like this:
controller
angular.module('JobSearch.SiteController', [])
.controller('JobSearchCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.getResults= getResults;
function getResults() {
$http.get('/api/JobShow/' + $scope.keyword + '/' + $scope.location).success(function (data) {
$scope.model = data;
});
}
}]);
html
<div ng-controller="JobSearchCtrl">
<input type="text" ng-model="keyword">
<input type="text" ng-model="location">
<button type="button" ng-click="getResults()">Search</button>
</div>
.controller('Search', function($scope) {
$scope.searchData = {};
$scope.searchItem = function($scope) {
return $scope.searchData.item;
}
.controller("SearchMeth", ["$scope", "$firebaseArray", function($scope, $firebaseArray) {
var cannedRef = new Firebase("https://pricemonitoringsys.firebaseio.com/dti")
// download the data from a Firebase reference into a (pseudo read-only) array
// all server changes are applied in realtime
$scope.cannedGoods = $firebaseArray(cannedRef);
// create a query for the most recent 25 messages on the server
//var query = cannedRef.orderByChild('category').equalTo('canned').on("child_added");
var query = cannedRef.orderByChild("category").equalTo($scope.searchData.search);
// the $firebaseArray service properly handles database queries as well
$scope.filteredMessages = $firebaseArray(query);
}
])
})
can anyone please help i cant seem to make this code work :( new at this and i have to make this work for my system
An easy way:
<div ng-app="app" ng-controller="mainController">
<div ng-controller="childController">
<div ng-controller="Search"></div>
<div ng-controller="Find"></div>
</div>
</div>
You can just define $scope.searchItem in mainController, that is, define it globally in the root controller, and then you can use it either in Search or other controllers.
How to synchronously bootstrap an angularjs app
I define a couple constant values on my app object. Some of these values need to be set via a call to a service and these calls need to complete before any of my controllers are instantiated.
In the example below, I define an array of values on an object named config. I need to set the value named PostIndexMenuID prior to any of my controllers being instantiated. How do I do that?
I have tried manually bootstrapping (removing ng-app from the html). I am not using routing.
Ideally I will not have to learn, download, install, configure, test, and maintain another framework to accomplish this.
(function()
{
angular.module('app', []);
var app = angular.module('app');
app.controller('controller', ['$scope', 'config', '$http', controller]);
app.service('menusService', ['$http', 'config', menusService]);
// Create config object. Some values are set in app.run
app.value('config', {
siteID: 100,
webRoot: '',
apiRoot: '/api',
imageRoot: '/Content/images',
PostIndexMenuID: 0
});
app.run(['$http', 'config','menusService', function ($http, config, menusService) {
menusService.GetMenuIDByName("PostIndex", function (data) {
config.PostIndexMenuID = data; // Need to complete this BEFORE GetPosts on the controller is called
});
}]);
function controller($scope, config, $http) {
var vm = this;
vm.Posts = 0;
function GetPosts() {
// In prod we call a service here get posts based on config.PostIndexMenuID
// for this example just return PostIndexMenuID.
vm.Posts = config.PostIndexMenuID;
};
GetPosts(); // need to delay calling this until AFTER PostIndexMenuID is set
};
function menusService($http, config) {
this.GetMenuIDByName = function (menuName, callBack) {
var uri = config.apiRoot + '/menu/GetMenuByName?menuName=' + menuName + '&siteID=' + config.siteID;
// use a timeout to simulate a slow service for this example and return a dummy value
var menuID = 99;
setTimeout(function () {
callBack(menuID);
}, 2000);
};
};
})()
// html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="app" >
<head>
<title></title>
</head>
<body >
<div ng-controller = "controller as vm">
<p>PostIndexMenuId is {{ vm.Posts }}</p>
</div>
<script src="Scripts/jquery-1.8.2.js"></script>
<script src="Scripts/angular.js"></script>
<script src="Scripts/angular-route.js"></script>
<script src="app/app.js"></script>
</body>
</html>
There is quite a nifty trick in Angular.js whereby you can defer the changing of a route until all promises have been resolved. You may have to restructure your application a little bit to cater for this approach, but I use it myself and it works like a treat!
$rootScope.$on('$routeChangeStart', function $routeChangeStart(event, next) {
// Extend the resolution of the route promise to wait for the user authentication
// process to determine if there's a valid session available.
next.resolve = angular.extend( next.resolve || {}, {
authenticating: api.isSession
});
});
By using the next.resolve you're extending Angular's sequence of promises that are resolved before a route change is considered a success. In the above case, as long as api.isSession returns a promise then everything will work wonderfully.
As soon as the api.isSession promise has been resolved, then the route change will succeed, and in your case, your controller will be loaded.