ng-model doesn't work btw 2 directives (ionic) - javascript

http://play.ionic.io/app/81ff26fc9a28
<body ng-app="app">
<ion-pane ng-controller="myCtrl">
<ion-header-bar class="bar-stable">
</ion-header-bar>
<ion-content class="padding">
<input ng-model="myInput" style="border:1px solid #ddd;width:100%;padding:5px" type="text" placeholder="search"/>
<br>
<br>
<br>
<br>
<br>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="search(myInput)" class="button button-block button-positive footer-btn" type="submit">able to get myInput value if put within ion-content</button>
</div>
</ion-footer-bar>
</ion-content>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="search(myInput)" class="button button-block button-positive footer-btn" type="submit">cannot get myInput value here</button>
</div>
</ion-footer-bar>
</ion-pane>
</body>
How to solve this problem? for the styling sake, I have to put the click event and input field in 2 different directives, but that causes the problem I couldn't get the value of ng-model.

This is a case where using $scope is problematic. One possible solution is to use the ControllerAs syntax instead.
The ControllerAs syntax allows you to easily identify which controller a particular function or property belongs to, and forces the "always use a dot" rule for angular, avoiding any prototype inheritance issues.
This isn't the only way to solve the problem, but this is a solution that will help build a more robust application with fewer issues related to $scope.
http://play.ionic.io/app/df429e85d209
angular.module('app', ['ionic'])
.controller('myCtrl', function() {
var ctrl = this;
ctrl.search = function(value) {
alert(value);
};
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<link href="https://code.ionicframework.com/1.0.0/css/ionic.min.css" rel="stylesheet">
<script src="https://code.ionicframework.com/1.0.0/js/ionic.bundle.js"></script>
</head>
<body ng-app="app">
<ion-pane ng-controller="myCtrl as ctrl">
<ion-header-bar class="bar-stable">
</ion-header-bar>
<ion-content class="padding">
<input ng-model="ctrl.myInput" style="border:1px solid #ddd;width:100%;padding:5px" type="text" placeholder="search" />
<br>
<br>
<br>
<br>
<br>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="ctrl.search(ctrl.myInput)" class="button button-block button-positive footer-btn" type="submit">able to get myInput value if put within ion-content</button>
</div>
</ion-footer-bar>
</ion-content>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="ctrl.search(ctrl.myInput)" class="button button-block button-positive footer-btn" type="submit">cannot get myInput value here</button>
</div>
</ion-footer-bar>
</ion-pane>
</body>
</html>

This is fixed code http://play.ionic.io/app/77035b24f58a
The issue is the $scope between two buttons are different, so the $scope.myInput value is not shared correctly.
One solution is add a $scope.model = {}; and refer to the model object like ng-model="model.myInput" and ng-click="search(model.myInput)". Then the inner scope will be access to the same model object.
This is the simplified code to demo this issue
var scope = {};
scope.myInput = '1';
var innerScope = Object.create(scope);
console.log(innerScope.myInput); // 1
innerScope.myInput = '2'; // myInput is 2 on innerScope
console.log(innerScope.myInput); // 2
console.log(scope.myInput); // 1 <-- but still 1 on scope
scope.model = {};
scope.model.myInput = '1';
console.log(innerScope.model.myInput); // 1
innerScope.model.myInput = '2'; //
console.log(innerScope.model.myInput); // 2
console.log(scope.model.myInput); // 2 <-- modify model.Input is visible on parent scope because they are modifying a same model object

Related

Why my onclick doesn't work?

I am new on this field, and have tried this for a long time. You can see my simple version here:
https://plnkr.co/edit/YeahrG28bT2izX8gMKor?p=preview
Could you tell me why my onclick here doesn't work? My button is the 2signUp botton, Thanks!
js:
var app = angular.module('myApp', []);
app.controller('mainControl', function($scope) {
$scope.logged = false;
$scope.visiter = true;
var sub1 = document.getElementsByClassName("haha")[0];
sub1.onclick=function(){
$scope.logged = !$scope.logged;
}
})
html:
<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="MainViewController.js"></script>
</head>
<body ng-controller="mainControl">
<div ng-show="logged">
<button>1Sign Up</button>
<button>Log In</button>
</div>
<div ng-show="visiter">
<button class="haha">2Sign Up</button>
<button>Log In</button>
</div>
<div ng-show="logged">
hello
</div>
</body>
Use the Angular way of handling click events, don't use any document.getElementById() jazz when you have angular to do the work for you.
This is why you should let angular handle it
Data Binding
Data-binding is an automatic way of updating the view whenever the model changes, as well as updating the model whenever the view changes. This is awesome because it eliminates DOM manipulation from the list of things you have to worry about.
https://angularjs.org/
Use Angular's ngClick
var app = angular.module('myApp', []);
app.controller('mainControl', function($scope) {
$scope.logged = false;
$scope.visiter = true;
$scope.signup = function() {
$scope.logged = !$scope.logged;
alert("ran the function");
}
})
<!DOCTYPE html>
<html lang="en" ng-app='myApp'>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="MainViewController.js"></script>
</head>
<body ng-controller="mainControl">
<div ng-show="logged">
<button>1Sign Up</button>
<button>Log In</button>
</div>
<div ng-show="visiter">
<button id="haha" ng-click="signup()">2Sign Up</button> <!-- use ngClick here! -->
<button>Log In</button>
</div>
<div ng-show="logged">
hello
</div>
</body>
</html>

Editing JSON search results from within Angular

I am now pulling data from a external JSON URL properly to the master page, but my detail page doesn't seem to pass on the object initallt received from http.get. This master part of the app can be viewed in a Code Pen at CODEPEN
<label class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="search" ng-model="query" placeholder="Search Slugname">
<button class="button button-dark" ng-click="getOrders()">Submit</button>
</label>
If my user wanted to change the date(order.date)value manually to say "10/8/16". How can I access/edit any of the JSON values that are returned from the external API?
I eventually wish to edit the returned JSON data within my app and then post that revised data back to a PHP API server.
Your main issue is that you want to modify the incoming data from the $http call.
You can implement an http interceptor, the method response will take the response modify it and then return it to the caller. Since the http interceptor will take all the incoming requests just check the url start to not modify other requests.
angular.module('ionicApp', ['ionic'])
.factory('httpInterceptor', function($q, $rootScope) {
var httpInterceptor = {
response: function(response) {
var deferred = $q.defer();
var results = response.data;
var urlStart = 'http://mvcframe.com/wpapi/wp-json/wp/v2/pages?slug=';
if (response.config.url.startsWith(urlStart)) {
angular.forEach(results, function(result, key) {
result.date = '10/8/16';
});
}
deferred.resolve(response);
return deferred.promise;
}
};
return httpInterceptor;
})
.config(function($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
})
.controller('ListController',
['$scope', '$http', '$state', '$stateParams', '$window', '$location',
function($scope, $http, $state, $stateParams, $window, $location) {
$scope.getOrders = function(query) {
$http.get('http://mvcframe.com/wpapi/wp-json/wp/v2/pages?slug=' + query)
.success(function(data) {
$scope.orders = data;
})
}
$scope.orders = [];
}]);
The only modification that I've made on your html is to send query param directly to the function on the ng-click
<html ng-app="ionicApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>Tabs Example</title>
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
</head>
<body ng-controller="ListController">
<ion-header-bar class="bar-dark" align-title="center">
<h2 class="title">Order Search</h2>
</ion-header-bar>
<ion-content padding="true" class="has-header">
<div class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="text" ng-model="query" placeholder="Search Slugname">
<button type="submit" class="button button-dark" ng-click="getOrders(query)">Submit</button>
</div>
<p>An example and working slug search term is test-3. The JSON can be viewable in a browser using https://mvcframe.com/wpapi/wp-json/wp/v2/pages?slug=test-3</p>
<ion-list>
<ion-item ng-repeat="order in orders | filter:query" class="item-thumbnail-left item-text-wrap" href="#/tab/list/{{order.id}}">
<h2>Page ID: {{order.id}}</h2>
<h3>Date created: {{order.date}}</h3>
<h2>Page URL: £{{order.link}}</h2>
<h2>Page Title: £{{order.title/rendered}}</h2>
</ion-item>
</ion-list>
</ion-content>
</body>
</html>
I almost forgot the codepen is here: http://codepen.io/pachon1992/pen/QEodJR
EDIT ---------------------------
As per comments you want your user to update manually the data right? as an example you would like to update the date, you can do enabling a input for the user to edit the data, since angular is two-way data-binding will modify your data.
<html ng-app="ionicApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>Tabs Example</title>
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
</head>
<body ng-controller="ListController">
<ion-header-bar class="bar-dark" align-title="center">
<h2 class="title">Order Search</h2>
</ion-header-bar>
<ion-content padding="true" class="has-header">
<div class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="text" ng-model="query" placeholder="Search Slugname">
<button type="submit" class="button button-dark" ng-click="getOrders(query)">Submit</button>
</div>
<p>An example and working slug search term is test-3. The JSON can be viewable in a browser using https://mvcframe.com/wpapi/wp-json/wp/v2/pages?slug=test-3</p>
<ion-list>
<ion-item ng-repeat="order in orders | filter:query" class="item-thumbnail-left item-text-wrap" href="#/tab/list/{{order.id}}">
<h2>Page ID: {{order.id}}</h2>
<div><input type="text" ng-model="order.date"></div>
<h2>Page URL: £{{order.link}}</h2>
<h2>Page Title: £{{order.title/rendered}}</h2>
</ion-item>
<button type="button" class="button button-dark" ng-click="update()">Update</button>
</ion-list>
</ion-content>
</body>
</html>
In your controller you can call http service for every order calling via typically to a PUT endpoint
angular.module('ionicApp', ['ionic'])
.controller('ListController', ['$scope', '$http', '$state', '$stateParams', '$window', '$location',
function($scope, $http, $state, $stateParams, $window, $location) {
$scope.query = "";
$scope.getOrders = function(query) {
$http.get('http://mvcframe.com/wpapi/wp-json/wp/v2/pages?slug=' + query)
.success(function(data) {
$scope.orders = data;
});
}
$scope.orders = [];
$scope.update = function() {
angular.forEach($scope.orders, function(order) {
//whetever url you are using
$http.put('http://mvcframe.com/wpapi/wp-json/wp/v2/pages/update/' + order.id, order, {})
.success(function(data) {
console.log('updated');
});
});
};
}
]);
I've edited the codepen
https://codepen.io/anon/pen/qNLOAP
So apparently it seems you cannot have a button in a <label> with ng-click. I changed the label to a <div> and it started working.
The search doesn't work at the moment but that should get you going.
Please resolve listed points.
1> tabs.home state you don't have injected controller and the other thing is also define home.html and
2> all other template separably in templates folder parallel to your controllers.
3> http call to http://mvcframe.com/wpapi/wp-json/wp/v2/pages requires cross origin domain support for that you can use chrome (CORS) plugin.
it will work for me. Please check and let me know if it works.
Working Pen:
https://codepen.io/jasondecamp/pen/gryxGQ
The two changes I made were:
1) Added $parent to the reference to 'query' in the input field ng-model. I am not that familiar with ionic, but my guess is that ion-content directive adds a child scope so to reference query you need to look to the parent.
<input type="search" ng-model="$parent.query" placeholder="Search Slugname">
2) I changed the http get url to be https because I was getting insecure access warnings.
As a note, you should not need to use any JSON parsing function when the response is pure JSON data, because angular $http service will automatically recognize the data and convert it into a js object.

Angular: when using ng-include, number variable become NaN [duplicate]

This question already has answers here:
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
(3 answers)
Closed 7 years ago.
I have a problem when i try to fragment my html with ng-include:
This is what my index.html page looks like when it works (prix=price, TVA=tax):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="style.css" />
<title> TVA </title>
</head>
<body>
<div>
<div ng-app="app" ng-controller="appCtrl">
<input ng-model="tva" placeholder="TVA" /><br />
<input ng-model="prix" placeholder="Prix" />
<select ng-model="taxe">
<option>HT</option>
<option>TTC</option>
</select>
<button id="btn" ng-click="calcul()">Calculer</button>
<p>{{ total }}</p>
</div>
</div>
<script src="angular.min.js"></script>
<script src="script.js"></script>
</body>
</html>
The script.js :
app = angular.module('app', []);
app.controller('appCtrl', ['$scope', function ($scope) {
$scope.calcul = function() {
if ($scope.taxe == "TTC") {
$scope.total = parseInt($scope.prix) + $scope.prix * $scope.tva /100;
} else if($scope.taxe == "HT") {
$scope.total = 1/(1+$scope.tva/100)*$scope.prix;
}
};
}]);
So this works, the result is an number (the price with or without tax).
When I use the ng-include like this:
<div>
<div ng-app="app" ng-controller="appCtrl">
<div ng-include="'tva.html'"></div>
<input ng-model="prix" placeholder="Prix" />
<select ng-model="taxe">
<option>HT</option>
<option>TTC</option>
</select>
<button id="btn" ng-click="calcul()">Calculer</button>
<p>{{ total }}</p>
</div>
</div>
I only tried to replace the first input with a new HTML page.
The tva.html :
<input ng-model="tva" placeholder="TVA" /><br />
Now the results show "NaN" (I put those codes on a server so that I can check online). Why is this?
#Josh Beam Answered & explained ng-include creates a child scope on creating the DOM. I'd suggest you to use dot rule in angular that will follow prototypal inheritance on that object and you object value will access in child scope.
Now your object structure will changed to $scope.model={}; and this model will have all the input values. like all will become like model.prix, model.taxe & model.tva so that the prototypal inheritance will follow.
Markup
<div ng-app="app" ng-controller="appCtrl">
<div ng-include="'tva.html'"></div>
<br />
<input ng-model="model.prix" placeholder="Prix" />
<select ng-model="model.taxe">
<option>HT</option>
<option>TTC</option>
</select>
<button id="btn" ng-click="calcul()">Calculer</button>
<p>{{ total }}</p>
</div>
Code
app.controller('appCtrl', ['$scope', function ($scope) {
$scope.model = {};
$scope.calcul = function() {
if ($scope.model.taxe == "TTC") {
$scope.total = parseInt($scope.model.prix) + $scope.model.prix * $scope.model.tva /100;
} else if($scope.model.taxe == "HT") {
$scope.total = 1/(1+$scope.model.tva/100)*$scope.model.prix;
}
};
}]);
tva.html
<input ng-model="model.tva" placeholder="TVA" /><br />
Demo Plunkr
Short answer: don't use ng-include in this instance.
Long answer: ng-include creates a new child scope, so ng-model inside the ng-include isn't appCtrl's TVA. I don't see a reason here to use ng-include anyway, your code is fine without it.
So basically you're getting NaN (not a number) because $scope.TVA is never set when using the ng-include... you're attempting to multiply an undefined variable by another number, which returns NaN:
The reason for that is the ng-include creates a new scope under the scope when the HTML was included, but you can access to the parent scope by specifying $parent
<input ng-model="$parent.tva" placeholder="TVA" /><br />
A better approach is give an alias to your controller, so it will be clear semantically to children controllers accessing to a specific parent.
<div ng-app="app" ng-controller="appCtrl as vmMain">
<div ng-include="'tva.html'"></div>
... and in the other file:
<input ng-model="vmMain.tva" placeholder="TVA" /><br />

How to make a On/Off button in Ionic

I need to put a button in Ionic that stays activated after it's been pressed, and only deactivates after it's been pressed again.
There is a similar question but it only applies to icon buttons. (How to adding navigation bar button having ionic-on/ ionic-off functionality).
EDIT
I can't use a toggle button, it is required to be a regular looking buttom (in this case an Ionic button-outline) that stays active when pressed.
Here is some code:
<div class="botones">
<div class="row">
<div class="col">
<button class="button button-outline button-block button-positive">
Promociones
</button>
</div>
<div class="col">
<button class="button button-outline button-block button-energized" >
Aprobados
</button>
</div>
<div class="col">
<button class="button button-outline button-block button-assertive" >
Alerta
</button>
</div>
<div class="col">
<button class="button button-outline button-block button-balanced" >
ATM
</button>
</div>
</div>
</div>
As you can see is a simple horizontal array of buttons. They suppose to act as filters for a message inbox, so they have to stay pressed (one at the time at most) as the filter is active. Like a tab but not quite.
The main question is, how can I access the activated state of the button so I can mantain it activated.
In Ionic, you can add class 'active' to a .button, to make it look pressed/active.
And to make only one active at a time, you can do something like this:
angular.module('ionicApp', ['ionic'])
.controller('MainCtrl', function($scope) {
$scope.buttons = [
{icon: 'beer', text: 'Bars'},
{icon: 'wineglass', text: 'Wineries'},
{icon: 'coffee', text: 'Cafés'},
{icon: 'pizza', text: 'Pizzerias'},
];
$scope.activeButton = 0;
$scope.setActiveButton = function(index) {
$scope.activeButton = index;
};
});
<html ng-app="ionicApp">
<head>
<link href="//code.ionicframework.com/1.1.0/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/1.1.0/js/ionic.bundle.js"></script>
</head>
<body ng-controller="MainCtrl">
<ion-content class="padding">
<div class="button-bar">
<button
ng-repeat="button in buttons"
ng-class="{'active': activeButton == $index}"
ng-click="setActiveButton($index)"
class="button icon ion-{{button.icon}}"
>
{{button.text}}
</button>
</div>
</ion-content>
</body>
</html>
Also, you can view a demo on Codepen.
You may find toggle button useful. Here's the official link to this example:
<ion-toggle ng-model="airplaneMode" toggle-class="toggle-calm">Airplane Mode</ion-toggle>
edit:
Here's a demo from Codepen
and the code pasted here:
angular.module('mySuperApp', ['ionic'])
.controller('MyCtrl',function($scope) {
});
<html ng-app="mySuperApp">
<head>
<meta charset="utf-8">
<title>
Toggle button
</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
</head>
<body class="padding" ng-controller="MyCtrl">
<button class="button button-primary" ng-model="button" ng-click="button.clicked=!button.clicked" ng-class="button.clicked?'button-positive':'button-energized'">
Confirm
</button>
</body>
</html>

AngularJS isn`t working

after watching this presentation (https://www.youtube.com/watch?v=ImR0zo1tA_I) I wanted to try Angular JS. I copied the code, exactly what was on the screen, but i doesn't work. I tried it in my browser, in my page (http://thecodemaker.com.pl), I was doing research about AngularJS but it still doesn`t want to work.
Code :
<!DOCTYPE html>
<html ng-app="basicApp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/bootstrap.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
</head>
<body ng-controller="TodoController">
<form>
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h1 class="panel-title"><b>ToDo List</b></h1>
</div>
<ul class="list-group">
<li class="list-group-item" ng-repeat = "todo in todos">
<div class="checkbox">
<label>
<input type="checkbox"> {{todo}}
</label>
<button type="button" class="close">×</button>
</div>
</li>
</ul>
</div>
<div class="form-group has-feedback">
<label class="control-label invisible">Enter Task</label>
<input type="text" class="form-control text-primary"></input>
<button type="button" class="close form-control-feedback text-muted">±</button>
</div>
<div class="alert alert-info">Enter new task to get started</div>
<div class="alert alert-danger">Maximum number of tasks allowed : 5</div>
</div>
</form>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery-1.11.2.js"></script>
<script>
angular.module("basicApp", [])
.controller("TodoController", ["$scope", function($scope) {
$scope.todos =['Buil an atomic bomb','Sell it on ebay']
}
</script>
</body>
</html>
Any ideas what is wrong ?
There seems to be a lot wrong with your snippet. For one, your submit/add button is not bound to an event listener or anything so it's not doing anything that you'd want (like adding an item to the property on your controller's $scope).
Check out the Todo example on Angular's official website, it's more up to date.
https://angularjs.org/ (scroll down).
Here's the video for it: https://www.youtube.com/watch?v=WuiHuZq_cg4
There is an error : Bootstrap's JavaScript requires jQuery, which means you need to add jQuery library to your project, required by bootstrap.js
Starting with Angular 1.3.x, you can no longer declare a controller as a generic global function on window. Controllers must now use the more current form of component declaration.
<script>
angular.module("basicApp", [])
.controller("TodoController", ["$scope", function($scope) {
$scope.todos =['Buil an atomic bomb','Sell it on ebay']
}
</script>
In the HTML, change ng-app="" to ng-app="basicApp.

Categories