i want to set the flag icon inside the header of my page depending on the selected language, using AngularJS. The language is selected in another .htm-file and its all brought together by AngularJS-routing.
My application uses one controller named "appController". The controller is inserted into the body-tag in "index.html". Inside "index.html" there is a that uses the angular function "setPicUrl()". The value of "appLang" is set by the radio-input in "language.htm", which is inserted into using routing by AngularJS.
The problem is, that the path for the flag icon does not change when i select another language (the variable "appLang" does). The icon is loaded correctly when i start the application.
routing.js
var app = angular.module("angApp", ["ngRoute"]);
app.config(function ($routeProvider) {
$routeProvider
.when("/visualization", {
templateUrl: "htm/visualization.htm",
controller: "appController"
})
.when("/data", {
templateUrl: "htm/data.htm",
controller: "appController"
})
.when("/social", {
templateUrl: "htm/social.htm",
controller: "appController"
})
.when("/about", {
templateUrl: "htm/about.htm",
controller: "appController"
})
.when("/language", {
templateUrl: "htm/language.htm",
controller: "appController"
});
});
controller.js
app.controller("appController", function ($scope, $http, $location) {
$scope.appLang = "english";
$scope.setPicUrl = function () {
if ($scope.appLang === "german") {
return "icons/german.png";
} else if ($scope.appLang === "english") {
return "icons/english.png";
} else {
//TODO Error handling
return;
}
};
index.html
<body ng-app="angApp" ng-controller="appController">
...
<li ng-class="{ active: headerIsActive('/language')}"><a href="#language"><img id="langpic"
ng-src="{{setPicUrl()}}"
class="img-responsive"></a>
...
<div ng-view></div>
</body>
language.htm
<div class="panel panel-default">
<div class="panel-heading">Spracheinstellungen</div>
<div class="panel-body">
<form>
Wählen Sie ihre Sprache aus:
<br/>
<input type="radio" ng-model="appLang" value="german">Deutsch
<br/>
<input type="radio" ng-model="appLang" value="english">Englisch
</form>
</div>
</div>
Thanks for your help! I got a solution:
The problem was, that the controller has been a copy of "appController" in each view and therefore the variables were different ones with the same name and the different views had no access to the same variable.
Now i use a service to share variables with other controllers and use an own controller for each view.
service:
app.factory("sharedProperties", function () {
return {
appLanguage: ""
};
});
langController:
app.controller("langController", function ($scope, sharedProperties) {
$scope.updateSharedProperties = function (){
sharedProperties.appLanguage = $scope.language;
console.log("--> updateSharedProperties(): " + $scope.language);
};
});
headerController:
app.controller("headerController", function ($scope, $http, $location, sharedProperties) {
$scope.setPicUrl = function () {
if (sharedProperties.appLanguage === "german") {
return "icons/german.png";
} else if (sharedProperties.appLanguage === "english") {
return "icons/english.png";
} else {
//TODO Error handling
return;
}
};
});
HTML for changing language (using langController):
<form>
Wählen Sie ihre Sprache aus:
<br/>
<input type="radio" ng-model="language" value="german" ng-click="updateSharedProperties()">Deutsch
<br/>
<input type="radio" ng-model="language" value="english" ng-click="updateSharedProperties()">Englisch
</form>
HTML for displaying flag-icon in header (using headerController):
<li><img id="langpic" ng-src="{{setPicUrl()}}" class="img-responsive"></li>
Try this. You need to execute the setPicUrl:
<input type="radio" ng-click="setPicUrl()" ng-model="appLang" value="german">Deutsch
<br/>
<input type="radio" ng-click="setPicUrl()" ng-model="appLang" value="english">Englisch
Change:
<img id="langpic" ng-src="{{setPicUrl()}}" class="img-responsive">
To:
<img id="langpic" ng-src="icons/{{appLang}}.png" class="img-responsive">
You can use $routeChangeStart or $routeChangeSuccess which are AngularJS built-in functions in bootstrapping function. For example when the route has been changed $routeChangeSuccess will be called automatically and you can change your $rootScope, $localStorage and any other directive's variables.
Try like this code:
//Bootstrapping Func
app.run(function ($window, $rootScope, $location, $route, $localStorage)
{
$rootScope.appLang = "english";
$rootScope.iconLang = "icons/english.png";
// On Route Change End Event
//---------------------------------------------
$rootScope.$on('$routeChangeSuccess', function ()
{
if ($rootScope.appLang === "german") {
$rootScope.iconLang = "icons/german.png";
} else if ($rootScope.appLang === "english") {
$rootScope.iconLang = "icons/english.png";
} else {
//TODO Error handling
}
});
}
Now you can bind the $rootScope.iconLang to the image tag you want like $scope.iconLang.
Related
Hi This is my first angularjs app and i am facing problem in injecting controller. I have one page called index.html and described as below.
<body ng-app="RoslpApp">
<div ng-controller="RoslpAppController">
<div class="popup">
<label>Language</label>
<select ng-model="selectedItem">
<option>العربية</option>
<option>English</option>
</select>
<button ng-click="clickHandler(selectedItem)">Submit</button>
</div>
</div>
</body>
This is my js file.
var app = angular.module('RoslpApp', ['pascalprecht.translate', 'ui.router']);
app.config(function ($stateProvider, $urlRouterProvider, $urlRouterProvider, $translateProvider, $translatePartialLoaderProvider) {
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('Registration', {
url: '/Registration',
templateUrl: 'Registration/Registration.html'
});
$translatePartialLoaderProvider.addPart('Main');
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: "Scripts/Locales/{part}/{lang}.json"
});
$translateProvider.preferredLanguage('en_US');
app.run(function ($rootScope, $translate) {
$rootScope.$on('$translatePartialLoaderStructureChanged', function () {
$translate.refresh();
});
});
app.controller('RoslpAppController', ['$scope', '$translate', function ($scope, $translate) {
$scope.clickHandler = function (key) {
$translate.use(key);
};
}]);
});
Whenever i select langualge from the dropdown and click on submit i get Argument RoslpAppController is not a function, got undefined error. May i get some help to fix this error?
Any help would be appreciated. Thank you.
Move the controller outside the app.config.
app.controller('RoslpAppController', ['$scope', '$translate', function ($scope, $translate) {
$scope.clickHandler = function (key) {
$translate.use(key);
};
}]);
I am new to angularjs. I want to pass data from html form to another route.
Here is the part of index.html
<div ng-app="myApp" ng-controller="HomeController">
<div class="container">
<div class="row">
<div class="col-md-12">
<div ng-view=""></div>
</div>
</div>
</div>
</div>
Here are the routes
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeController'
});
$routeProvider.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
});
}]);
When the route is / it hits the views/home.html in which it has a form
<form action="#/about" ng-submit="submitData()">
<input type="text" name="address" ng-model="user.address" />
<input type="submit" />
</form>
I have a user service whose implementation is
myApp.factory("user", function () {
return {};
});
I inject user service in HomeController like
myApp.controller("HomeController", function ($scope, user) {
$scope.user = user;
// and then set values on the object
// $scope.user.address = "1, Mars"; // when uncomment this line it can be accessed on AboutController? Why? Otherwise I cannot access user.address
console.log($scope.user);
});
Don note my comment in above code..
and passes user to AboutController like
myApp.controller("AboutController", function ($scope, user) {
$scope.user = user;
// and then set values on the object
$scope.user.firstname = "John";
$scope.user.secondname = "Smith";
console.log($scope.user);
});
Here is the about.html
<p>
{{ user.address }}
</p>
Problem: {{user.address}} doesn't work on AboutController. I can't see any output... But when i remove the comment from above code.. It only displays hardcoded values in the controller What am I missing?
This is the working demo http://ashoo.com.au/angular/#/
At the moment, all your service does is pass a blank object return {}, to any controller into which it is injected. You need a getter/setter approach, so that in your Home view you can set the data, and in your About view you can retrieve it.
So your service could look something like this:
myApp.factory("user", function () {
var dataObj = {};
return {
setData: function(data) {
dataObj.username = data.username;
},
getData: function() {
return dataObj;
}
};
});
Now you can set the data in your Home controller:
myApp.controller("HomeController", function ($scope, user) {
$scope.submitData = function(data) { //pass in ng-model
user.setData(data); //call 'user' service to set data
}
});
And call it from your About controller:
myApp.controller("AboutController", function ($scope, user) {
$scope.user = user.getData(); //Assign
console.log($scope.user.username);
});
And you html would look like:
<form action="#/about" ng-submit="submitData(user.username)">
<input type="text" name="address" ng-model="user.username" />
<input type="submit" />
</form>
I am trying to display a modal with the information of a certain item. But when I call the function it reads:
TypeError: Cannot read property 'open' of undefined at Scope.$scope.openModal
I was hoping someone could tell me why, here is the relevant code:
Template
<div ng-controller="View1Ctrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Item Details</h3>
</div>
<div class="modal-body">
<ul ng-repeat="i in items">
<li>Type: <span ng-bind="i.type"></span></li>
<li>Description: <span ng-bind="i.description"></span></li>
<li>Date: <span ng-bind="i.createDate"></span></li>
<li>Priority: <span ng-bind="i.priority"></span></li>
<li>Finished: <span ng-bind="i.isDone"></span></li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="$close()">OK</button>
</div>
</script>
</div>
App.Js
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', [
//'ngRoute',
'ui.router',
'ui.bootstrap',
'myApp.view1',
'myApp.view2',
'myApp.version',
'myApp.items'
])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/view1');
$stateProvider
.state('view1', {
url: '/view1',
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
})
.state('view2', {
url: '/view2',
templateUrl: 'view2/view2.html',
controller: 'View2Ctrl'
});
});
Controller
'use strict';
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
.controller('View1Ctrl', ['$scope','itemsService',function($scope,itemsService, $uiModal) {
$scope.$on('itemSwitch.moreInfo', function(event, obj){
$scope.openModal(obj);
});
$scope.openModal = function (obj) {
var modalInstance = $uiModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'templates/modalTemplate.html',
controller: 'View1Ctrl',
resolve: {
items: function () {
return obj;
}
}
});
}
}]); //END
Can anyone point me in the right direction to fix this issue?
Thanks
The error is gone, but now it doesn't show anything but the grey-out screen, the console shows the modal html is loading but not displaying properly.
Your injection signature is not correct. You are missing $uiModal. Observe the following...
.controller('View1Ctrl', ['$scope', 'itemsService',
function($scope, itemsService, $uiModal) {
=>
.controller('View1Ctrl', ['$scope', 'itemsService', '$uiModal',
function($scope, itemsService, $uiModal) {
I am not totally sure the exact name of the service you are intending to inject. I guess here based on your variable that is named $uiModal, however, I notice the docs state it is $uibModal. You'll need to verify this.
In response to your updated newly found issue, my best observation is that templateUrl: '' and <script id=""> must match. Try changing your <script> tag to the following...
<script type="text/ng-template" id="templates/modalTemplate.html">
<!-- <div> -->
I stumbled upon this while playing around with the default plunker found in the docs. If both values are not the same there is an error.
I am new to angular JS.How can I redirect to another page when the button is clicked.
My code here
var app = angular.module("plunker", [])
.config(function ($routeProvider, $locationProvider, $httpProvider) {
$routeProvider.when('/home',
{
templateUrl: 'home.html',
controller: 'HomeCtrl'
});
$routeProvider.when('/about',
{
templateUrl: 'about.html',
controller: 'AboutCtrl'
});
$routeProvider.when('/contact',
{
templateUrl: 'contact.html',
controller: 'ContactCtrl'
});
$routeProvider.otherwise(
{
redirectTo: '/home',
controller: 'HomeCtrl',
}
);
});
app.controller('NavCtrl',
['$scope', '$location', function ($scope, $location) {
$scope.navClass = function (page) {
var currentRoute = $location.path().substring(1) || 'home';
return page === currentRoute ? 'active' : '';
};
}]);
app.controller('AboutCtrl', function($scope, $compile) {
console.log('inside about controller');
});
app.controller('HomeCtrl', function($scope, $compile) {
console.log('inside home controller');
//redirect when button click
function Cntrl ($scope,$location) {
$scope.redirect = function(){
window.location.href = '/about';
}
}
});
app.controller('ContactCtrl', function($scope, $compile) {
console.log('inside contact controller');
});
my html markup is
<div ng-controller="Cntrl">
<button class="btn btn-success" ng-click="changeView('about')">Click Me</button>
</div>
You entered :
How to get this.help me to solve this .
Just use a standard HTML link :
<div ng-controller="Cntrl">
<a class="btn btn-success" ng-href="#/about">Click Me</a>
</div>
No need to create a scope function for that. You can also handle that dynamically thanks to ng-href :
<div ng-controller="Cntrl">
<a class="btn btn-success" ng-href="#/{{view}}">Click Me</a>
</div>
Last thing, you should consider using ui-router which handle even better this cases
Why do you need to send the view as a param:
Try this:
$scope.changeView = function() {
$location.path(#/about);
}
If solution that Cétia presented does not work, then it is possible that you do not have your routes defined. Make sure that you have your route defined withing app.js like this :
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/Login', {
templateUrl: 'Navigate/LoginView',
controller: 'someLoginController'
})
]);
You can as well use angulars state provider (do some research) and from state provider you can access your routes within html as :
<a href="state.routName" />
I need to track when a user changes the state of a checkbox in Ionic, save it to localStorage, and then use it to load again later - so it remembers their settings.
My toggle code looks like this:
<li class="item item-toggle">
National Insurance {{ni_toggle}}
<label class="toggle toggle-positive">
<input type="checkbox" ng-model="ni_toggle" ng-click="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
<div class="track">
<div class="handle"></div>
</div>
</label>
</li>
And in my controller I have:
angular.module('starter.controllers', [])
.controller('SettingsCtrl', function($scope, $ionicPlatform) {
$ionicPlatform.ready(function() {
// Ready functions
});
$scope.updateLocalStorage = function() {
window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
console.log( $scope.ni_toggle );
}
})
However, it logs out to the console as undefined. If I explicitly set $scope.ni_toggle = false; it will log false and won't update to true when I toggle the checkbox to on.
EDIT:
app.js:
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.settings', {
url: '/settings',
views: {
'tab-settings': {
templateUrl: 'templates/tab-settings.html',
controller: 'SettingsCtrl'
}
}
})
.state('tab.info', {
url: '/info',
views: {
'tab-info': {
templateUrl: 'templates/tab-info.html',
controller: 'InfoCtrl'
}
}
})
.state('tab.about', {
url: '/about',
views: {
'tab-about': {
templateUrl: 'templates/tab-about.html',
controller: 'AboutCtrl'
}
}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
});
controllers.js:
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope) {
})
.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
$ionicPlatform.ready(function() {
});
$scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === "true";
$scope.updateLocalStorage = function() {
$window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
console.log( $scope.ni_toggle );
}
})
.controller('InfoCtrl', function($scope) {
})
.controller('AboutCtrl', function($scope) {
});
templates/tab-settings.html:
<li class="item item-toggle">
National Insurance {{ni_toggle}}
<label class="toggle toggle-positive">
<input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
<div class="track">
<div class="handle"></div>
</div>
</label>
</li>
Working example of the problem
I am not familiar with Ionic's oddities (if there are any), but from a general JS perspective there seem to be a few issues with your code.
You are not initializing ni_toggle.
You are using ngClick which will get fired before the model has been updated by the ngModel directive.
You should use ngChange instead.
In Angular, you should use $window instead of window (it doesn't hurt and it can prove useful in many cases (e.g. testing)).
Note that localStorage can only store strings (not booleans). So, even if you pass false, it will be stored as 'false', which is equivalent to true when cast to boolean.
Taking the above into account, your code should look like this:
<input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" ... />
.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
$ionicPlatform.ready(function() {
// Ready functions
});
$scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === 'true';
$scope.updateLocalStorage = function () {
$window.localStorage.setItem('has_national_insurance', $scope.ni_toggle);
console.log($scope.ni_toggle);
};
});
See, also, this short demo.
I ran into a similar situation for displaying user information a while ago with my ionic app. I don't have my original source code in front of me but I'm pretty sure this is how you need to do it.
angular.module('starter.controllers', [])
.controller('SettingsCtrl', function($scope, $ionicPlatform) {
this.toggle = true; // make sure its defined somewhere
$scope.ni_toggle = function() {
return this.toggle;
}
$scope.updateLocalStorage = function() {
window.localStorage.setItem(
'has_national_insureance',
$scope.ni_toggle
);
console.log($scope.ni_toggle);
}
});
Hope this gets you going in the right direction.
EDIT
See ExpertSystem's answer. He answered it way better than I could.
No need of any function definition in controller
<script>
angular.module('checkboxExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.checkboxModel = {
value1 : true,
value2 : 'YES'
};
}]);
<form name="myForm" ng-controller="ExampleController">
<label>Value1:
<input type="checkbox" ng-model="checkboxModel.value1">
</label><br/>
<label>Value2:
<input type="checkbox" ng-model="checkboxModel.value2"
ng-true-value="'YES'" ng-false-value="'NO'">
</label><br/>
<tt>value1 = {{checkboxModel.value1}}</tt><br/>
<tt>value2 = {{checkboxModel.value2}}</tt><br/>