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/
Related
I am trying to get the value from sessionStorage and map it to my ng-model, but
when i do that in my ng-init its not working.
The problem is in my actual code i am inside a ng-repeat so my sessionStorage becomes like below:
sessionStorage.getItem(item.itemId)
HTMl Code:
<div ng-app="">
<div ng-controller="MyCtrl">
Not Working <input ng-init = 'name = sessionStorage.getItem("SavedString")' type="text" ng-model="name" >
Working <input type="text" ng-model="name1" >
</div>
</div>
Controller:
function MyCtrl($scope) {
sessionStorage.setItem("SavedString","I'm a value saved with SessionStorage");
//RETRIEVE VALUE
$scope.name = "test"
$scope.name1 = sessionStorage.getItem("SavedString");
$scope.hi = 'Hello World';
}
Fiddle:
http://jsfiddle.net/393revrn/
i too tried in your way but i didn't find a the requirements to achieve this ......so i tried with making a function call with in init and appended session data to that model then i can see the proper output by making ng-init ='some()' here is the working plunker
UPDATE
From some source i found that HTML cannot understand session variables directly.
The sessionStorage, when accessed from the ng-init directive, is not understood by Angular; it will be parsed and interpreted as if it were a $scope function (which, I assume, is not).
So, in order for your example to work, you should do something like this in your controller:
$scope.sessionStorage = sessionStorage;
What I want to accomplish, is to be able to feed the modal box with data data so it can correctly display it. You can see here the jsfiddle where the simple test is located.
http://jsfiddle.net/GabrielBarcia/sjtog46f/1/
In my current learning project, I am using Bootstrap tabs and modal boxes, that is why I have the modal defined on the beginning of the code. On the real project, if I define the modal inside the tabs it is not correctly displayed, therefore I needed to ¨declare¨ it before the tabs start for it to work.
I was hoping that because triggering the modal from inside the controller, the directive on the modal had access to the data, but it seems like I was wrong. I have tried several ways but could not make it work, this is why I am asking for help. I need the directive to be able to show data on the modal as it does on the test of the directive inside the controller. Hope you guys can help
Here is working as I was expecting
<div ng-controller="dataInputCtrl">
<div>
<p>value A :
<input type="textbox" ng-model="userData.a"></input>
</p>
<p>value B :
<input type="textbox" ng-model="userData.b"></input>
</p>
</div>
<div>
<render-item directivedata="userData"></render-item> //Here is ok!
</div>
Here is not
<div class="modal-body">
<render-item directivedata="userData"></render-item> //here not ok
</div>
Simple workaround would be bind the data to both controller and modal directive through a service
angular.module('app', [])
.controller('dataInputCtrl', function ($scope, DataServ) {
// data bound to service
$scope.userData = DataServ.data;
}).factory('DataServ', function () {
return {
data: {}
};
}).directive('renderItem', function (DataServ) {
return {
restrict: 'E',
template: "<p> A = {{data.a}}</br>B = {{data.b}}</p>",
link: function (scope, elem, attrs) {
// data bound to service rather than passed from attribute
scope.data = DataServ.data
}
};
});
You will still find using angular-ui-bootstrap a lot less problematic in the long run. It is heavily used and actively developed
DEMO
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 the following code:
<input id="id">
<button data-action="bea" ng-click="Create($('#id1')[0].value);" class="btn">Insert ID</button>
<button data-action="bea" ng-click="Create($('#id2')[0].value);" class="btn">Insert ID</button>
In the JS I have:
$scope.Create = function (id){
if (id === undefined) {
$scope.data = "You must specify an id";
} else {
$scope.data = data;
console.log(data);
});
}
};
When the call gets into the Create function the value of the id is undefined.
If I add the following line at the beginging of the Create function everything works ok:
id = $('#id')[0].value;
If I send a constant value it works:
<button data-action="bea" ng-click="Create('SomeID');" class="btn">Insert ID</button>
Why is this happening and how can I do that without putting the line of value into the method?
Thanks
This is just an extension of comments and other answers, You could achieve this in many ways using angular, one simple example could be:-
<!-- Add a controller -->
<div ng-controller="MainCtrl">
<!-- Give a model binding to your text input -->
<input ng-model="userEntry" type="text"/>
<!-- ng-click pass which ever argument you need to pass, provided it is an expression that can be evaluated against the scope or any constants -->
<button data-action="bea" ng-click="Create(userEntry);" class="btn">Insert ID</button>
<!-- Some simple data binding using interpolation -->
{{data}}
<!-- Just for demo on repeater on a list of items on the scope -->
<div ng-repeat="item in items track by $index">{{item}}</div>
</div>
Example Demo
My 2 cents on the lines of what were originally trying to do:-
Use angular bindings instead of accessing DOM directly for getting the data, it really helps you deal with just the data without worrying about how to access or render it in DOM. If you think you need to access DOM for implementing business logic re-think on the design, if you really need to do it, do it in a directive. Angular is very opinionated on the design and when where you do DOM access.
ng-model
ng-binding
controller
all about ngmodel controller
This is not the way you should do in AngularJS. You should really think in Angular if you want to use AngularJS. Refer this post ("Thinking in AngularJS" if I have a jQuery background?)
All DOM manipulation should be done in Directive. Refer this page that I found really clear.
(http://ng-learn.org/2014/01/Dom-Manipulations/)
My guess is that $ is not bound to the jQuery function when the ng-click value is evaluated, because it is not exposed in the Angular scope.
Solutions to adress this:
expose the jQuery function in scope somewhere, e.g $scope.$ = $; in a controller.
make the Create function parameterless as you suggested, with a var id = $('#id')[0].value; at the beginning
my favorite : avoid using jQuery. If you put some data in the #id element, there's probably a more natural and AngularJS-idiomatic way of retrieving it than querying the DOM (e.g an Angular service).
In particular, if the element you're targeting is an <input> element, then use the ngModel directive to link the value to a $scopeproperty that will be accessible in the controller :
<input ng-model="inputData"/>
The JavaScript you are trying to pass as a parameter of the create function is not available in the scope of the Create function.
Try to target the element a different way.
Does that help?
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}}