I have a very strange issue. Using AngularJS 1.5.8. With previous versions it didn't work either. Functions like ng-bind, ng-model, ng-submit work fine.
Click on "Inschrijven" http://adr-opleiding.ismiami.com/, second step "Postcode" and enter e.g. 1000. It will display Amsterdam. I used a div element w/ ng-bind="city". If I use {{city}} it will always display {{city}}. I can't get it to update from a controller.
angular.module('app', []).controller('HomeController', ['$rootScope', '$scope', '$stateParams', function($rootScope, $scope, $stateParams) {
$scope.$on('$viewContentLoaded', function() {
$scope.app.settings.htmlClass = $stateParams.htmlClass.website;
$scope.app.settings.bodyClass = '';
});
}])
.controller('WizCtrl', ['$scope', '$http', function($scope, $http) {
$scope.city = '';
$scope.printCity = function(){
if($scope.postcode.length == 4) {
$http({
method: 'POST',
url: '/db/get.php',
data: { action: 'retCity', zip: $scope.postcode }
})
.then(function success(response) {
$scope.city = response.data.city;
}, function error(response) {
});
}
}
}]);
And here's the HTML:
<div class="form-group">
<label for="wiz-postcode" class="col-xs-4 control-label">Postcode:</label>
<div class="col-xs-3">
<input class="form-control" type="text" name="wiz-postcode" id="wiz-postcode" style="width: 80px;" placeholder="Postcode" ng-keyup="printCity()" ng-model="postcode" onblur="this.value=this.value.toUpperCase()" />
</div>
<div class="col-xs-5" ng-bind="city" style="padding-top: 8px; font-size: 1.1em;"></div>
</div>
At the very top of the HTML I have a div element w/ the controller:
<div ng-controller="WizCtrl">
So the question is how come that $scope variables work fine for everything except updating the view w/ a variable like this {{test}}
A new Google search "angularjs variables in braces not working" got me to AngularJS-Twig conflict with double curly braces from which I learned that w/ AngularJS you can set the symbols w/ the variables start and endSymbol
var app = angular.module('app')
.config(
[ '$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$interpolateProvider',
function ($controllerProvider, $compileProvider, $filterProvider, $provide, $interpolateProvider) {
app.controller = $controllerProvider.register;
app.directive = $compileProvider.directive;
app.filter = $filterProvider.register;
app.factory = $provide.factory;
app.service = $provide.service;
app.constant = $provide.constant;
app.value = $provide.value;
$interpolateProvider.startSymbol('::');
$interpolateProvider.endSymbol('::');
}
]);
Related
I am trying to auto post a form from a controller without any user interaction on the form. I have a private init() function in the controller that triggers a button click on the form.
But the hidden form fields did not get the values yet. How can I make sure the hidden fields will have values populated before the form submits?
Thank you for any suggestions.
<div>
<form name="myForm" method="post" action="#Model.Settings["URL"]" ng-controller="MyCtrl">
<input type="hidden" name="userid" value="{{UserSettings.Settings.UserId}}">
<input type="hidden" name="amount" value="{{Payment.Amount}}">
<button id="payButton" type="submit" class="action blue"><span class="label">Pay</span></button>
<script language="javascript">
var UserSettings = (function (o) {
return o;
})(#Html.Raw(JsonConvert.SerializeObject(#Model)));
</script>
</form>
</div>
myControllers.controller('MyCtrl', ['$scope', '$state', '$element', 'dataService',
function ($scope, $state, $element, service) {
$scope.Payment = service.GetPayment());
$scope.UserSettings = UserSettings;
function init() {
// How can I force to have values in the hidden form fields before the button click that submits the form ?
$element.find('#payButton').trigger("click");
};
init();
}]);
Here is the ui-router states configuration.
var app = angular.module('pay', ['ui.router', 'pay.controllers', 'pay.services', 'exceptionOverride', 'ngSanitize']);
app.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/' ,
templateUrl: 'search'
})
.state('payment', {
url: '/payment',
templateUrl: 'Payment'
});
//setting html5 removes the # from URL but causes routing problems at the moment.
//$locationProvider.html5Mode(true);
$urlRouterProvider.rule(function ($injector, $location) {
//what this function returns will be set as the $location.url
var path = $location.path(), normalized = path.toLowerCase();
if (path != normalized) {
$location.replace().path(normalized);
}
else if (path == '') {
$location.path('/');
}
});
}]);
You can put the populations in the point you define the state which has MyCtrl as follows:
.state('myState', {
// ...
resolve: {
Payment: ['dataService', function (dataService) {
return dataService.GetPayment();
}],
// Same for other objects needed
}
})
And then in your Controller:
myControllers.controller('MyCtrl', ['$scope', '$state', '$element', 'Payment',
function ($scope, $state, $element, Payment) {
$scope.Payment = Payment;
// Same for other objects needed
// Rest code
}
The code in the Controller would not start running before all actions and promises in the resolve section finish.
Update:
You can put init call inside a $timeout.
$timeout(function(){
init();
});
Of course, you have to inject $timeout in Controller function along with the other dependencies.
All the documentation out there for AngularJS 1.6 is extremely ambiguous. Everybody has tutorials for how to do $http.get requests, but nothing on how to properly setup $http.post requests for version 1.6.
All I'm trying to do is setup a controller that gives my mini-project the functionality to allow the user to type in his/her city into the input box on the Home page and, when they submit it, the information for their forecast will appear on the Forecast page. So, theoretically, the controller will 'POST' data into the URL to be able to retrieve information from the Open Weather API. The Routes and everything else works just fine...I only need help for this POST method stuff.
My apologies for my code looking unintelligible. I just posted what I had.
As an aside, does anybody have REALLY good resources for documentation on AngularJS 1.6?
(function () {
'use strict';
// MODULE
angular.module("WeatherApp", ['ngRoute', 'ngResource', 'http'])
// ROUTES
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'templates/home.html',
controller: 'homeCtrl'
})
.when('/forecast', {
templateUrl: 'templates/forecast.html',
controller: 'forecastCtrl'
});
})
// SERVICES
.service('cityService', function () {
this.city = "Chicago";
})
// CONTROLLERS
.controller("homeCtrl", function ($scope, cityService) {
$scope.city = cityService.city;
$scope.$watch('city', function () {
cityService.city = $scope.city;
});
})
.controller("forecastCtrl", function ($scope, $http, cityService) {
$scope.city = cityService.city;
$http.post("http://api.openweathermap.org/data/2.5/forecast/daily", {q: $scope.city, cnt: 2, appid: "8a3dfe91838e8409da30958ed6b68932"}).then(function (data) {
console.log();
});
});
})();
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h4>Forecast by City</h4>
<div class="form-group"><input ng-model="city" type="text" class="form-control"></div>
Get Forecast
</div>
</div>
Here is an example of using $http.post. The API returns with an error and I hope you can investigate on that.
angular
.module('MyApp', []);
angular
.module('MyApp')
.controller('ForecastController', [
'$scope',
'$http',
function($scope,
$http) {
$scope.vm = {
city: 'Newyork',
errorMessage: ''
}
$scope.getForecast = function() {
var vm = $scope.vm;
console.log('Getting forecast for ' + vm.city + ' city');
/*$http.get("http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1")*/
$http.post("http://api.openweathermap.org/data/2.5/forecast/daily", {
q: vm.city,
cnt: 2,
appid: "8a3dfe91838e8409da30958ed6b68932"
})
.then(function(data) {
console.log('Got forecast successfully.');
}, function(error) {
var message = 'There was an error getting forecast';
console.log(message);
console.log(error);
vm.errorMessage = message;
});
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<style>
.item-row {
margin-bottom: 10px;
}
.item-row:last-child {
margin-bottom: 0;
}
</style>
<div ng-app="MyApp">
<div ng-controller="ForecastController">
<div class="item-row" ng-show="vm.errorMessage">
{{vm.errorMessage}}
</div>
<div class="item-row">
<input type="text" ng-model="vm.city" />
</div>
<div class="item-row"> You entered: {{vm.city}}</div>
<div class="item-row">
<button ng-click="getForecast()">Get Forecast</button>
</div>
</div>
</div>
I want to make a sidebar with list item that can be dynamically changed based on the settings page.
My app request settings.json via factory() and then called it in a controller. The controller will be used by settings.html (ngView) and sidebar.html (ngInclude).
The json will return Boolean value that also can be changed on setting page that contain checkbox which return true if check and false if not checked. I use ngShow on the sidebar to display/hide the list items.
How can I made the sidebar to reflect the changes as I tick the checkbox?
settings.factory.js
var settingsFactory = angular.module('settingsFactory', []);
settingsFactory.factory('SettingsFilterFactory', ['$http', function ($http) {
var settingsFactory = {};
settingsFactory.getSettings = function () {
return $http.get('app/data/settings.json');
};
return settingsFactory;
}]);
controller
var settingsControllers = angular.module('settingsControllers', ['settingsFactory']);
settingsControllers.controller('SettingsFilterController', ['$scope', '$http', 'SettingsFilterFactory', function ($scope, $http, SettingsFilterFactory) {
$scope.settings;
$scope.status;
getSettings();
function getSettings() {
SettingsFilterFactory.getSettings()
.then(function (response) {
$scope.settings = response.data;
}, function (error) {
$scope.status = 'Unable to load: ' + error.message;
});
}
}]);
app.js
var app = angular.module('app', ['ngRoute', 'settingsControllers']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/settings', {
title: 'Settings',
templateUrl: 'app/components/settings/settings.html',
controller: 'SettingsFilterController'
}).
otherwise({
redirectTo: '/home'
});
}]);
My index.html is something like this:
...
<body>
<section class="sidebar">
<div ng-include="'app/components/sidebar/sidebar.html'"></div>
</section>
<section class="content">
<div ng-view></div>
</section>
</body>
...
sidebar.html
<ul class="sidebar-menu" ng-controller="SettingsFilterController">
<li ng-show"settings.hiddenMenu">This is secret link</li>
</ul>
settings.html
...
<div class="checkbox">
<input type="checkbox" ng-model="settings.hiddenMenu" ng-true-value=true ng-false-value=false> Check this to show hidden menu
</div>
...
Try something like this (untested):
settings.factory.js
var settingsFactory = angular.module('settingsFactory', []);
settingsFactory.factory('SettingsFilterFactory', ['$http', function ($http) {
var settingsFactory = {};
settingsFactory.getSettings = function () {
return $http.get('app/data/settings.json');
};
settingsFactory.hiddenMenu= true;
settingsFactory.someOtherSetting = {};
return settingsFactory;
}]);
sidebar controller
settingsControllers.controller('SidebarController', ['$scope', '$http', 'SettingsFilterFactory', function ($scope, $http, SettingsFilterFactory) {
//do this in each controller, so that the factory becomes a property of $scope and can be seen in the HTML
$scope.settingsFactory = SettingsFilterFactory;
}
sidebar.html
<ul class="sidebar-menu" ng-controller="SidebarController">
<li ng-show"settingsFactory.hiddenMenu">This is secret link</li>
</ul>
settings.html
...
<div class="checkbox">
<input type="checkbox" ng-model="settingsFactory.hiddenMenu" ng-true-value=true ng-false-value=false> Check this to show hidden menu
</div>
...
Essentially, you are binding the settingsFactory object which is a singleton to each $scope that is provided by each controller. Each controller is able to change the property on the factory object, which is then visible in all other controllers that have injected this object.
I have an main page with ng-view defined.
My routing pulls in several templates.
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
})
.when('/view2', {
templateUrl: 'view2/view2.html',
})
.otherwise({redirectTo: '/view1'});
}]);
My First template looks like this:
<p>This is the partial for view 1.</p>
<div ng-controller="View1Ctrl">
<input type="text"
ng-model="search"
ng-model-options="{ debounce: 800 }"
placeholder="Enter full movie name"
autofocus />
</div>
The JS for this template looks like this;
'use strict';
angular.module('myApp.view1', [])
.controller('View1Ctrl', [function($scope, $http) {
$scope.$watch('search', function() {
fetch();
});
function fetch(){
alert("it werky");
}
}]);
Why am I getting the error: angular.js:13708 TypeError: Cannot read property '$watch' of undefined?
I'm essentially pulling in a template with models and directives defined on it but I don't think those are being run.
May be your dependencies are not getting injected, you are passing an array with the constructor function as it's only element.
Here is a working plunk.http://plnkr.co/edit/U2hxQPBZMVo2jaR4bwsq?p=preview
myApp.controller('View1Ctrl', ['$scope', '$http', function($scope, $http) {
alert ("jaiHo");
$scope.$watch('search', function() {
fetch();
});
function fetch(){
alert("it werky");
}
}]);
Try this:
'use strict';
angular.module('myApp.view1', [])
.controller('View1Ctrl', ['$scope', '$http', function($scope, $http) {
$scope.$watch('search', function() {
fetch();
});
function fetch(){
alert("it werky");
}
}]);
Note how I inject dependencies
Try this
(function () {
'use strict';
angular.module('myApp.view1', [])
.controller('View1Ctrl', function($scope, $http) {
var vm = this;
$scope.$watch('vm.search', function(newValue, oldValue) {
fetch(newValue, oldValue);
}, true);
function fetch(newValue, oldValue){
vm.newValue = newValue;
vm.oldValue = oldValue;
}
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp.view1">
<div ng-controller="View1Ctrl as vm">
<input ng-model="vm.search" type="text" />
<div>
Old Value: {{vm.oldValue}}
</div>
<div>
New Value: {{vm.newValue}}
</div>
</div>
</div>
I'm downloading some data using firebase before presenting new controller's view, but the template "blinks" before showing the data. I have no idea why, it should show the data instantly without any delay. I've recorded it and marked each individual frame (http://i.imgur.com/pUsMCqX.gif). Console logs the data that resolve object returns. You can see that when data is being logged, the template is being shown with no data at frames 2 and 3.
Template:
<div ng-cloak class="wrapper select-character">
<div>
<div>
<h1>Select character</h1>
<div>
<button ng-click="createNewCharacter()">create new character</button>
</div>
characters' list
</div>
</div>
<div ng-repeat="character in characters">
<div>
Name: {{ character.name }}
<br>
Level: {{ character.level }}
<br>
<button ng-click="enterWorld(character.name)">Choose</button>
</div>
</div>
</div>
Controller:
'use strict';
angular.module('App')
.controller('SelectCharacterCtrl', function($scope, $firebaseSimpleLogin, $location, characters) {
$scope.createNewCharacter = function() {
$location.path("/create-character");
};
$scope.enterWorld = function(name) {
alert(name);
};
$scope.characters = characters;
});
App:
'use strict';
angular.module('App', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
'firebase',
'angularfire.firebase',
'angularfire.login'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/log-in.html',
controller: 'LogInCtrl'
})
.when('/select-character', {
templateUrl: 'views/select-character.html',
controller: 'SelectCharacterCtrl',
resolve: {
characters: function($q, $timeout, $firebase, $firebaseSimpleLogin) {
var deferred = $q.defer();
var loginObj = $firebaseSimpleLogin(new Firebase("https://<id>.firebaseio.com"));
loginObj.$getCurrentUser()
.then(function(user) { // get login data
var userSync = $firebase(new Firebase('https://<id>.firebaseio.com/users/' + user.uid));
return userSync.$asObject().$loaded();
})
.then(function(user) { // get all characters
var promises = [];
angular.forEach(user.characters, function(name) {
var promise = $firebase(new Firebase('https://<id>.firebaseio.com/characters/' + name));
promises.push(promise.$asObject());
});
$q.all(promises).then(function(sth) {
console.log(sth);
deferred.resolve(sth);
});
});
return deferred.promise;
}
}
})
.when('/create-character', {
templateUrl: 'views/create-character.html',
controller: 'CreateCharacterCtrl'
})
});
Why does the template "blinks" with no data for 2 frames before updating the scope? Any ideas?
Since $asObject does not return a promise, your list of promises are immediately resolved (instead of after all the data is downloaded). Change your list to return promises too:
angular.forEach(user.characters, function(name) {
var promise = $firebase(new Firebase('https://<id>.firebaseio.com/characters/' + name));
promises.push(promise.$asObject().$loaded());
});