I am working with onsen-ui and I have the following problem:
I have a stack of onsen's components like that:
-->ons-sliding-menu var="menu"
|
|-->ons-page
|
-->ons-list-item
|
|-->ons-switch var=myswitch
Why can't I reference the var 'myswitch' from inside an angular controller? The angular controller is set in the ons-page tag.
Thank you in advance.
Sure it works, you can see the working CodePen HERE. As you can see, I used the <ons-switch> methods isChecked() and setChecked(isChecked) without any problem. If you need more than one switch don't use var but use ng-model and bind it to a variable inside the controller and manage the elements from there. This is an example, you can find the working CodePen HERE
ONE SWITCH
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script>
angular.module('myApp', ['onsen'])
.controller('DemoController', function($scope) {
$scope.changeSwitchStatus = function(){
if($scope.mySwitch.isChecked())
$scope.mySwitch.setChecked(false);
else
$scope.mySwitch.setChecked(true);
};
});
</script>
</head>
<body>
<ons-sliding-menu var="app.slidingMenu" menu-page="menu.html" main-page="page1" side="left" type="overlay" max-slide-distance="200px">
</ons-sliding-menu>
<ons-template id="page1">
<ons-navigator ng-controller="DemoController">
<ons-page>
<ons-toolbar>
<div class="left">
<ons-toolbar-button ng-click="ons.slidingMenu.toggleMenu()"><ons-icon icon="bars"></ons-icon></ons-toolbar-button>
</div>
<div class="center">Page 1</div>
</ons-toolbar>
<ons-list>
<ons-list-item class="item">
<ons-switch var="mySwitch"></ons-switch>
</ons-list-item>
</ons-list>
<ons-button ng-click="changeSwitchStatus()">Change switch status</ons-button>
</ons-page>
</ons-navigator>
</ons-template>
</body>
</html>
MULTIPLE SWITCHES
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script>
angular.module('myApp', ['onsen'])
.controller('DemoController', function($scope) {
$scope.switch = [
{
status: false
},
{
status: false
}
];
$scope.changeSwitchStatus = function(){
for(var i = 0; i < $scope.switch.length; i++){
$scope.switch[i].status = !$scope.switch[i].status;
}
};
});
</script>
</head>
<body>
<ons-sliding-menu var="app.slidingMenu" menu-page="menu.html" main-page="page1" side="left" type="overlay" max-slide-distance="200px">
</ons-sliding-menu>
<ons-template id="page1">
<ons-navigator ng-controller="DemoController">
<ons-page>
<ons-toolbar>
<div class="left">
<ons-toolbar-button ng-click="ons.slidingMenu.toggleMenu()"><ons-icon icon="bars"></ons-icon></ons-toolbar-button>
</div>
<div class="center">Page 1</div>
</ons-toolbar>
<ons-list>
<ons-list-item class="item" ng-repeat="item in switch">
<ons-switch ng-model="item.status"></ons-switch>
</ons-list-item>
</ons-list>
<ons-button ng-click="changeSwitchStatus()">Change switch status</ons-button>
</ons-page>
</ons-navigator>
</ons-template>
</body>
</html>
Related
First, I am a beginner in the process of learning. I have been experimenting with this code to load remote json data in to a ons-list. Can someone explain to me why the data is not loading in to the list? I am using Monaca. I can get the data to show up when using the UL tag. It just won't show up in the ons-list tag. Your help is very much appreciated!
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
<script src="components/loader.js"></script>
<script src="lib/angular/angular.min.js"></script>
<script src="lib/onsenui/js/onsenui.min.js"></script>
<script src="lib/onsenui/js/angular-onsenui.min.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="lib/onsenui/css/onsenui.css">
<link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css">
<link rel="stylesheet" href="css/style.css">
<script>
ons.ready(function() {
console.log("Onsen UI is ready!");
});
</script>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$http.get("http://www.w3schools.com/angular/customers.php").then(function (response) {
$scope.myData = response.data.records;
});
});
</script>
</head>
<body>
<ons-page ng-app="myApp" ng-controller="customersCtrl">
<ons-toolbar>
<div class="center">Introduction</div>
</ons-toolbar>
<ul>
<li ng-repeat="x in myData">
{{ x.Name + ', ' + x.Country }}
</li>
</ul>
<ons-row ng-repeat="x in myData">
<ons-col>{{ x.Name }}</ons-col>
<ons-col>{{ x.Country }}</ons-col>
</ons-row>
<ons-list ng-controller="customersCtrl">
<ons-list-item ng-repeat="x in myData">
{{ x.Name }}
</ons-list-item>
</ons-list>
</ons-page>
</body>
</html>
I was able to figure it out. I needed to change the line of code below.
var app = angular.module('myApp', ['onsen']);
This is the error msg.
Error: This function is not registered in the lock list.
at Object.window.DoorLock.DoorLock._unlock (loader.js:1450)
at window.DoorLock.DoorLock.lock.unlock (loader.js:1450)
at Scope.parent.$get.Scope.$broadcast (loader.js:1444)
...
index.html
<!DOCTYPE HTML>
<html ng-csp>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<script src="js/winstore-jscompat.js"></script>
<link rel="stylesshet" href="components/monaca-onsenui/js/angular/angular-csp.css">
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script src = "./js/prog.js" ></script>
</head>
<body ng-app = "magic_land" >
<ons-navigator var="captain" page="list.html">
</ons-navigator>
</body>
</html>
...
list.html
<div >
<ons-toolbar>
<div class = "center">All todoz</div>
</ons-toolbar>
<ons-list>
<ons-list-item>Apple</ons-list-item>
<ons-list-item>Banana</ons-list-item>
<ons-list-item>Carrot</ons-list-item>
</ons-list>
<p> {{5+5}} </p>
</div>
...
prog.js
var magic_land = ons.bootstrap('magic_land', ['onsen']);
Where is this error coming from?
Before
<body ng-app="magic_land" ng-controller = "magic_action">
<ons-navigator var="captain" page="list.html" >
</ons-navigator>
</body>
After
<body >
<ons-navigator var="captain" page="list.html" ng-app="magic_land" ng-controller = "magic_action" >
</ons-navigator>
</body>
Now that error is gone!
I know, this code is different from the question , but it was a tough error so i had to swap and rearrange my codes to find the source of error. Good luck!
I'm using an ons-modal to show a loading text and spinner icon when the app is fetching some data.
The code is as follows:
<ons-modal var="loadingModal">
<ons-icon icon="ion-load-c" spin="true"></ons-icon>
<br><br>
Cargando...
<br>
</ons-modal>
I can correctly show an hide it using loadingModal.show(); and loadingModal.hide();
But how would I know in Angular if it is shown or hidden?
Update
Apparently my not-so-elegant solution is not not so elegant after all :D
Here is a pull request that shows the method isShown() that should be available
soon I guess
Internally the function looks similar to whats in this answer
isShown() {
return this.style.display !== 'none';
}
Not a super elegant solution, but it works
if( $scope.loadingModal._element.css('display') == 'none'){
// hidden now
}else{
// visible now
}
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<title>Modal | Onsen UI</title>
<link rel="stylesheet" href="https://rawgit.com/OnsenUI/OnsenUI/master/demo/styles/app.css"/>
<link rel="stylesheet" href="https://rawgit.com/OnsenUI/OnsenUI/master/build/css/onsenui.css">
<link rel="stylesheet" href="https://rawgit.com/OnsenUI/OnsenUI/master/build/css/onsen-css-components.css">
<script src="https://rawgit.com/OnsenUI/OnsenUI/master/build/js/angular/angular.js"></script>
<script src="https://rawgit.com/OnsenUI/OnsenUI/master/build/js/onsenui.js"></script>
<script src="https://rawgit.com/OnsenUI/OnsenUI/master/demo/app.js"></script>
<script>
function check($el){
return $el.css('display') === 'none' ? 'hidden' : 'visible';
}
angular.module('myApp').controller('PageController', function($scope) {
$scope.open = function() {
$scope.app.modal.show();
alert(check($scope.app.modal._element));
setTimeout(function() {
$scope.app.modal.hide();
alert(check($scope.app.modal._element));
}, 2000);
};
});
</script>
</head>
<body ng-controller="PageController">
<ons-navigator>
<ons-modal var="app.modal">
<ons-icon icon="ion-load-c" spin="true"></ons-icon>
<br><br>
Cargando...
<br>
</ons-modal>
<ons-toolbar>
<div class="center">Modal</div>
</ons-toolbar>
<p style="text-align: center">
<ons-button modifier="light" ng-click="open();">Open Modal</ons-button>
</p>
</ons-navigator>
</body>
</html>
<ons-list id="myList"></ons-list>
Then a statement in a loop that does
$('#myList').append("<ons-list-item>" + variableItem + "</ons-list-item>");
And probably some sort of a refresh like so
$('#myList').listview('refresh');
after exiting from the loop.
Can this be done without angular?
Add item via javascript, like:
var listElement = document.getElementById('myListElement'); //My ons-list element
var newItemElement = document.createElement('ons-list-item'); //My new item
newItemElement.innerText = 'Lorem ipusm dolor'; //Text or HTML inside
//Update ons render
ons.compile(listElement);
#Rafa's answer is correct, but you seemed to use jQuery instead of plain JS.
#Ataru's answer utilizes jQuery, but lack ons.Compile();
ons.compile() is required to generate regular HTML from onsen directives (custom Web Components) since not all browser support them (yet).
Here's sum up:
$('#myList').append("<ons-list-item>" + variableItem + "</ons-list-item>");
ons.compile($('#myList')[0]);
index.html
<!DOCTYPE HTML>
<html ng-app="yourApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- If you don't use Monaca, please comment out here and load Onsen UI directly. -->
<script src="components/loader.js"></script>
<script src="jquery.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script>
var yourApp = angular.module('yourApp', ['onsen']);
yourApp.controller('listCtrl', function($scope, $timeout) {
// Add new list ith jQuery.
var onsList = $("#ons-list-test");
onsList.append('<ons-list-item class="list__item ons-list-item-inner">Item 1</ons-list-item>');
onsList.append('<ons-list-item class="list__item ons-list-item-inner">Item 2</ons-list-item>');
onsList.append('<ons-list-item class="list__item ons-list-item-inner">Item 3</ons-list-item>');
onsList.append('<ons-list-item class="list__item ons-list-item-inner">Item 4</ons-list-item>');
onsList.append('<ons-list-item class="list__item ons-list-item-inner" style="background:#999999;">Item 5</ons-list-item>');
});
</script>
</head>
<body>
<ons-navigator title="Navigator" var="myNavigator" page="page1.html">
</ons-navigator>
</body>
</html>
page1.html
<ons-page>
<ons-toolbar>
<div class="center">Navigator</div>
</ons-toolbar>
<div style="text-align: center" ng-controller="listCtrl">
<ons-list id="ons-list-test">
</ons-list>
</div>
</ons-page>
Thank you.
You can add your new list by using jQuery as following:
What worked for me is:
<ons-list id="list4" >
<ons-list-header>Grocery list</ons-list-header>
<ons-list-item >Broccoli</ons-list-item>
<ons-list-item>Oranges</ons-list-item>
</ons-list>
<script>
var m = "Apples & Pears"
var item = ons._util.createElement("<ons-list-item> </ons-list-item>");
item.innerHTML = m;
document.getElementById("list4").appendChild(item);
</script>
Maybe you have to add compile to it, the internet is not sure about it (-;
Just trying to get a handle on angularJS as was building a simple little app where you can make a list of people and in the list their names are colored. The color is chosen by a select drop-down box.
The trouble is any way I try to add the new color to a style I run into trouble. At this point names get added to the list correctly, but they don't get colored correctly and I get the following error:
Error: [$parse:syntax] Syntax Error: Token 'undefined' not a primary expression at column null of the expression [{color:] starting at [{color:].
http://errors.angularjs.org/1.2.16/$parse/syntax?p0=undefined&p1=not%20a%20primary%20expression&p2=null&p3=%7Bcolor%3A&p4=%7Bcolor%3A
at http://localhost:8000/app/bower_components/angular/angular.js:78:12
at Parser.throwError (http://localhost:8000/app/bower_components/angular/angular.js:10266:11)
at Parser.primary (http://localhost:8000/app/bower_components/angular/angular.js:10239:14)
at Parser.unary (http://localhost:8000/app/bower_components/angular/angular.js:10492:19)
at Parser.multiplicative (http://localhost:8000/app/bower_components/angular/angular.js:10475:21)
at Parser.additive (http://localhost:8000/app/bower_components/angular/angular.js:10466:21)
at Parser.relational (http://localhost:8000/app/bower_components/angular/angular.js:10457:21)
at Parser.equality (http://localhost:8000/app/bower_components/angular/angular.js:10448:21)
at Parser.logicalAND (http://localhost:8000/app/bower_components/angular/angular.js:10439:21)
at Parser.logicalOR (http://localhost:8000/app/bower_components/angular/angular.js:10427:21) <li ng-repeat="player in players" ng-style="{color:" "stylecolor(player)"}="" class="ng-scope ng-binding">
Which I think means player.color is coming back null? If there is a way to do this without the function call that would be preferable I was just trying emulate this solution:
dynamically adding directives in ng-repeat
Here is my html:
<!DOCTYPE html>
<!--[if lt IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html lang="en" ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html lang="en" ng-app="myApp" class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html lang="en" ng-app="myApp" class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Scratch Snake</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="bower_components/html5-boilerplate/css/normalize.css">
<link rel="stylesheet" href="bower_components/html5-boilerplate/css/main.css">
<link rel="stylesheet" href="css/app.css"/>
<script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"> </script>
<!-- Bootstrap files -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<script src="bower_components/jquery/dist/jquery.js"> </script>
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
</head>
<body ng-controller = "PlayerAdditionCtrl">
<ul class="list-group">Players:
<li ng-repeat="player in players" ng-style = {color: "styleColor(player)"} > {{player.name}} </li>
</ul>
<div id="playerEntry">
<p>
<label for="playername">Name: </label><input id="playername" class="form-control" type="text" name="playername" ng-model="playername">
<select id="playerColor" ng-model="playercolor">
<option value="#f00">Red</option>
<option value="#00f">Blue</option>
<option value="#0f0">Green</option>
<option value="#ff0">Yellow</option>
</select>
</p>
<button type="button" class = "btn btn-primary" id="addPlayerBtn" ng-click="addPlayer()">Add Player</button>
<button type="button" class = "btn btn-success" id="doneBtn" onclick="moveToGame();">All Done!</button>
<button type="button" class = "btn btn-info" id="defaultsBtn" onclick="loadDefaults();">Load Defaults</button>
<br>
</div>
<!-- In production use:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script>
-->
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
</body>
</html>
And my controller:
'use strict';
/* Controllers */
angular.module('myApp.controllers', [])
.controller('PlayerAdditionCtrl', ['$scope', function($scope) {
$scope.players = [];
//add a player
$scope.addPlayer = function()
{
$scope.players.push(
{
name: $scope.playername,
color: $scope.playercolor
});
}
$scope.styleColor = function (player)
{
return { color: player.color }
}
}]);
remove
$scope.styleColor() in your controller
change
<li ng-repeat="player in players" ng-style = {color: "styleColor(player)"} > {{player.name}} </li>
to
<li ng-repeat="player in players" ng-style="{color: player.color}" > {{player.name}} </li>
Change
<li ng-repeat="player in players" ng-style = {color: "styleColor(player)"} > {{player.name}} </li>
to
<li ng-repeat="player in players" style="color: {{player.color}};"> {{player.name}} </li>
If you stick with ng-style, two-way data binding will update every player to the selected color. Without using angular.copy, changing your data structure, or doing something else to break two-way data binding, it won't be possible to have players be different colors.
Here's a working Plunker example: http://plnkr.co/edit/wEpKzN?p=preview