The two way binding in AngularJs is great in updating the view anytime the model changes. I was wondering if there was some way to pass the model to a function defined in the controller before being displayed. And not with a button click but live.
So for example, the p element would be updated automatically
<input data-ng-model='myModel'>
<p>{{myModel}}</p>
Is there any way to do the following?
<div data-ng-controller='myController'>
<input data-ng-model='myModel'>
<p>{{increment(myModel)}}</p>
</div>
where increment is a function defined in myController
Most definitely you can. Just define the function in the same controller. For instance
Controller:
app.controller('myCtrl', function($scope) {
$scope.increment = function() {
return $scope.myModel;
}
});
HTML
<div data-ng-controller='myController'>
<input data-ng-model='myModel'>
<p>{{increment()}}</p>
</div>
That returns the exact same thing as {{myModel}}
Related
Can I use ng-model to build up an object over several views?
For instance, say in view1 I have
<input ng-model='myObject.firstName'>
And in view2 I have
<input ng-model='myObject.lastName'>
And in view3 I have
<input ng-model='myObject.email'>
The idea being you could hit a submit button in the last view, and return the object somewhere.
My initial approach to this is to have a service which declares an empty object, then have functions in the service which allow the controllers using the service to add their view input to that object, then return the object.
However I feel like this is quite a roundabout way of doing it!
If anyone could point me in the right direction I would really appreciate it.
You can use a service for that. Here an example with 3 controllers sharing the same object using 3 directives ng-model. Each controller modify the tested.value property, but you can use differents properties of course.
angular.module('test', []).factory('tested', function() {
return {
value : '123'
};
}).controller('ctrl1', function($scope, tested) {
$scope.tested = tested;
}).controller('ctrl2', function($scope, tested) {
$scope.tested = tested;
}).controller('ctrl3', function($scope, tested) {
$scope.tested = tested;
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="ctrl1">
<input type="text" ng-model="tested.value" />
{{ tested.value }}
</div>
<div ng-controller="ctrl2">
<input type="text" ng-model="tested.value" />
{{ tested.value }}
</div>
<div ng-controller="ctrl3">
<input type="text" ng-model="tested.value" />
{{ tested.value }}
</div>
</div>
Since each view has its controller, the only way to share data is with a service of type "provider", "service" or "factory".
You could then modify your object from each controller with the methods you talk about.
In the end, to notify each view something changed, the service methods could raise an event from the service :
$rootScope.$broadcast('somethingChanged', myObject);
And each controller could listen with:
$scope.$on('somethingChanged', function(data) {
});
this is my html file:
<section data-ng-controller="myCtrl">
{{name}}
<button id="btn1">Button1</button>
</section>
this is my controller:
angular.module('users').controller('myCtrl', ['$scope',
function($scope) {
$scope.name="HELLO";
document.getElementById("btn1").addEventListener("click",function(){
$scope.name="changed";
});
}]);
the html file displays HELLO but it does not changes to "changed" on clicking the button.
i am new to angular can someone please help me..
It's because regular event listeners don't trigger a $digest cycle within Angular, which is what will update the view. You should be using ngClick and defining a $scope function:
$scope.clickHandler = function() { $scope.name = "changed"; };
And the HTML:
<button ng-click="clickHandler()">Button1</button>
I have in my code, some html elements that are added later on the page. but when you add it later, the directive ng-click does not work.
Another solution I've tried was to call a node method on this later added element using onclick attribute, but it means call a angularJs method outsite the controller and it's not possible (if so, could be a nice solution for many type of problems)
here's the jsfiddle example:
http://jsfiddle.net/hugoofab/wktqrhv3/1/
here's the markup:
<div ng-app="myApp" ng-controller="MyController" >
<button type="button" ng-click="testFunction('this will work')">STEP 1. this will work</button>
<button type="button" ng-click="addElement()" >STEP 2. add button</button>
<div id="foodiv"></div>
<button type="button" onclick="anotherWay()" >STEP 4. another way</button>
Here's the javascript:
var myApp = angular.module('myApp', []);
function anotherWay ( ) {
alert("another way would be call node method outside, but how to do it?")
// ohhh man.. what I'll code here?
//myApp.controller.scope()..... I really don't know
}
myApp.controller('MyController', function($scope) {
$scope.testFunction = function ( a ) {
alert(a)
}
$scope.addElement = function ( ) {
document.getElementById('foodiv').innerHTML = '<button type="button" ng-click="testFunction(\'this will not work\')">STEP 3. this will not work</button>' ;
}
});
Thank's!
It seems you're doing things in a "non-angular" way...
First of all, this happens to you because you add these elements after angular has $compiled the view.
One way of doing this the "angular way", is using an ng-show/ng-hide directive with your buttons, and showing/hiding them using the controller.
Another way is having something like this:
$scope.buttons = [{ }, { }];
And adding buttons to this array using the controller. Then render this array in your view using ng-repeat.
I have been ploughing into AngularJS and am trying to get my head around how everything links together but I've become a bit stuck.
How can I pass a variable to change the JSON that is loaded and shown on the page?
I thought it would be a button click and the directive would talk to the controller, but how I'm not so sure.
If i have my JSON as something like this as in controller...
var id = 'peter';
var person = $resource('http://myjson.com/'+id+'.json')
I can't figure out how I would change the id based on button clicks for example.
Any help is greatly appreciated
I'll try to explain as simple as possible, you can pass data as argument to a function from HTML to controller using the ngClick directive.
The function inside the controller will be invoked because it has a binding to the ngClick directive using the $scope.
Example:
html:
<div ng-app="App" ng-controller="ctrl">
<div ng-repeat="itemId in items">
<button ng-click="myClickFunc(itemId)">click {{itemId}}</button>
</div>
</div>
js:
var app=angular.module('App', ['ngResource']);
function ctrl($scope,$resource){
$scope.items=[1,2,3,4];
$scope.myClickFunc=function(itemId){
var person = $resource('http://myjson.com/get/:id');
person.get({id: itemId}).$promise.then(function(data) {
// success
$scope.myData = data;
}, function(errResponse) {
// fail
});
}
Live example: http://jsfiddle.net/choroshin/zJ5G6/
I've created a jsFiddle: check it out
Currently, when creating the scopes they are not isolated. Therefore, if i create two input fields and type in one of them the text is duplicated in the secondary inputfield.
How can I create multiple inputs, fill them out individually and submit them all at the same time?
html
<div ng-app="miniapp" ng-controller="MainCtrl">
<a href="" data-clicker>add inputs</a>
<form ng-model="project" ng-submit="addPage()">
<div class="sections"></div>
<input type="submit" value="submit"/>
</form>
<hr>
<hr>
<p>project: {{project.name | json}}</p>
<p>output: {{output | json}}</p>
</div>
JS
var $scope;
var app = angular.module('miniapp', []);
app.directive('clicker', function($compile) {
'use strict';
return {
compile: function(tElement, tAttrs) {
//var t = '<div data-pop>Pop</div>';
var t = '<div><input type="text" ng-model="project.name"></div>';
return function(scope, iElement) {
iElement.click(function() {
$('.sections').append($compile(t)(scope));
});
};
}
}
});
app.controller('MainCtrl', function($scope) {
$scope.project = {"name":"sup"};
$scope.output = [];
$scope.addPage = function() {
$scope.output.push(_.clone($scope.project));
};
});
I feel like I've tried everything... Is it just a flaw in my logic? If so, can you show me an example that works according to the user flow below?
User Flow
You should use Angular's ng-repeat directive to iterate through an array of objects and generate the input fields with data-binding.
Here is a simplified version of your code using the directive: http://jsfiddle.net/89AYX/42/
With ng-repeat, everything within the block becomes a template that get compiled automatically for each iteration of an array model. Think of it like a for-each loop in HTML that updates itself when the array changes.
<div ng-repeat="project in projects">
<input type="text" ng-model="project.name"/>
</div>
As you can see, the project variable becomes accessible within the block as a reference to an object in the array. You can then use that reference to create a two-way binding on the input field with a property of that particular object.
Angular comes with a lot of useful built-in directives that solves a lot of common issues involving data-binding. Be sure to check out their API reference to see what's available.
whenever you create a new input you are attaching the same model property to it project.name
var t = '<div><input type="text" ng-model="project.name"></div>';
switch that access a different attribute for each. or make an attribute an array if you can do that