I'm writing a simple AngularJS example that doesn't have a controller. It just uses the default global controller/model.
<!DOCTYPE html>
<html lang="en" ng-app=>
<body>
<input type="text" ng-model="firstName" placeholder="first name">
<input type="text" ng-model="lastName" placeholder="last name">
<br />
<h2 ng-style=style>Welcome {{firstName + ' ' + lastName}}</h2>
<button ng-disabled="!(firstName.length && lastName.length)">Sign Up</button>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
</body>
</html>
Where are the firstName and lastName values stored? This form works as expected so the two-way binding is working. I've tried looking through the window object and I didn't see anything in there that might be the global Angular controller. If I wanted to submit these values, where would the "handle" to them be in this example?
UPDATE
As I said, this is working as evidenced by this jsFiddle. The name is computed correctly and the button is only enabled once both firstName and lastName have values. I also tried using Batarang and it did not help. It told me that there wasn't a scope defined yet the application still functions.
Try installing Batarang and inspecting for yourself, though I believe those two values would be applied to $rootScope
You can view your scope using ng-inspector. It may not work in js-fiddle, because they do things with iframes that hide the global variables the inspector depends on.
I tried it on a test application with an unnamed module, as in your example, and it discovers the scope as $rootScope 002
Because of this I theorized, and have found through experiment, that the scope of an application without a declared module name (and probably with one, too) is attached to whatever DOM node the ng-app directive is on.
So, if you put ng-app on the html tag, this would get you your scope:
angular.element(
document.getElementsByTagName('html')[0]
).scope();
Using JSFiddle will complicate this testing, since it does iFrame stuff and has multiple html and body tags. Try it in an isolated environment and it's pretty straight-forward.
In console, select the result frame, and type:
angular.element($('body')).scope().firstName
You should see the firstName value. With regards to "If I wanted to submit these values" part, I believe you want to do an ajax call with these values. The best place to do that is by attaching a controller, where you will have direct access to these variables, and then you can use $http service to post to a server.
Related
I am new to javascript and angular so,i would appreciate your help, before I start plz have a look at below two pictures-
After some time there is a change-
Now some attributes in below HTML code has same attribute, -
<input type="text"
class="menuTitleField ng-pristine ng-untouched ng-valid ng-isolate-scope ng-valid-required"
ng-model="title" placeholder="Option Name" elastic-input=""
ng-required="isRequired" focus-on="newChild" focus-if="canFocus"
tabindex="0" required="required" style="min-width: 0px; width: 48px;">
For example, there are canFocus or title, in HTML and in above picture, so how can I get the value of canFocus, title using java script based on class name or tag name or event.target.id?
I think these values come from the sever, how can I get values of those attribute?
Plz, ask in comment for clarification, also edit the post for more precise question. thanks.
so how can I get the value of canFocus using java script
Use either:
$rootScope.canFocus
or
$scope.$root.canFocus
To use $rootScope,$scope in your controllers, you need to import it then you can use variables to get values like
$scope.title
$scope.canFocus
if you want to use $rootScope just use this
$rootScope.title
$rootScope.canFocus
In your HTML
title,canFocus should work with your code
Angular has an angular way of doing almost everything. In this instance I would suggest researching property binding. For example with the placeholder property you can write:
<input [placeholder]="someVariable">
Then declare the someVariable in your component and what ever you set it to will be the placeholder and you can access it that way. The [] lets you set it to a variable in your component and will update the placeholder whenever you change it in your component. I would try experimenting with this to get an understanding for how it works.
First of all: I am absolutely new to AngularJS but worked on MVC-projects in other languages.
I try to bind a Property containing HTML.
This is the code:
HTML:
<div ng-controller="MyController">
<p>{{About}}</p>
</div>
JS:
.controller('MyController', ['$scope', function($scope) {
$scope.About="This is me<br/>and not you!"
}
Now the HTML is encoded which I do not want (the <br/> should result in line breaks)
I already tried <p ng-bind-html="About"></p> but that resulted in no output at all
You need to allow html in your text which Angular does not by default.
Plunker: http://plnkr.co/edit/K4KRCQi4Rpe99MJel5J2?p=preview
Angular Docs for $sce
Strict Contextual Escaping (SCE) is a mode in which AngularJS requires
bindings in certain contexts to result in a value that is marked as
safe to use for that context. One example of such a context is binding
arbitrary html controlled by the user via ng-bind-html. We refer to
these contexts as privileged or SCE contexts.
<div ng-controller="htmlChar" ng-bind-html="about"></div>
<script>
angular.module("app",[])
.controller("htmlChar",function($scope, $sce){
$scope.about= $sce.trustAsHtml("This is me<br/>and not you!");
});
angular.bootstrap(document,["app"]);
</script>
You shoudln't need to insert html through model binding in AngularJS since the philosophy of the framework is to keep the HTML (page's structure and style) intact and only bind the data to be shown inside that HTML.
If you really need to bind HTML tags into your data you need to use the $sanitize service.
You have to use angular compile functionality here, go through the link to get more information angular compile
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?
I have an app with many forms. Each field has several HTML elements, so I thought I could extract some directives (one per type of field) to keep my forms tidy.
I've created a sample app to demonstrate the problem, but I'm getting inconsistent behavior. In the sample app, a <link /> element replaces the <input />. In my real app, <input /> just gets removed from the DOM completely. I feel like this should be easy; why doesn't it work?
To answer your stated question, it's because you told it to, with ng-transclude. That replaces the contents of the tag with the original element, which I don't think you wanted; you probably wanted the original contents to be transcluded as the label instead.
This is probably what you're looking for:
<div class="form-group" >
<label for="{{htmlId}}" ng-transclude></label>
<input id="{{htmlId}}" class="form-control" type="text" ng-model="model" />
<span ng-repeat="error in errors">{{error}}</span>
</div>
I've moved the tranclusion into the label. While this works, I would also recommend the style of actually passing a label attribute, rather than transclude it, just for the sake of having a consistent API and simpler code; it's functionally equivalent, though, so don't let me bully you.
Also, you've got a few errors in your .js as well. First, you want to use = in your scope instead of &
scope: {
model: '=',
errors: '='
},
& is used to pass methods, while = is used for objects (this is a simplification). Since your model and errors are objects, you'll want to use = instead.
Finally, in your example, your html template and your directive's template don't have the same name... you've got an extra 's' in your .js, but that's probably just in the plunker and not your real app.
I am trying to understand data binding in Angularjs.
What I want to do is establish binding between pages that is if I change the input on first.html, the data should automatically change in second.html.
For example,
This is first.html:
<div ng-controller="MyCtrl">
<input type="text" ng-model="value"/><br>
{{value}}
<input type="submit" value="Second page"/>
</div>
and say second.html has only this piece of code {{value}}.
and in the .js file we have $routeProvider which takes the template url as 'second.html' & the controller is 'MyCtrl'.
So the controller is:
MyApp.controller(function($scope){
$scope.value="somevalue";
})
By doing the above way the {{value}} on the second.html is getting the value "somevalue". Which is comming from the controller.
But if I change the input value dynamically that is on the first.html, the value on the second.html is not getting that value.
My question is how do I bind the value on second.html with first.html automatically.
To understand the question clearly, Suppose there is an input field for entering text and a submit button on first.html, then I want to get the Input value of the text field of the first.html on the second.html page on Submit.
Use a service and store your model there. Gloopy already has a good example of this here: https://stackoverflow.com/a/12009408/215945
Be sure to use an object property instead of a primitive type.
If you'd rather use $rootScope, then as above, define an object, rather than a primitive:
$rootScope.obj = { prop1: "somevalue" }`
then bind to that object property in your views:
<input type="text" ng-model="obj.prop1">
{{obj.prop1}}
If you attach your data to $rootScope if will survive transitions across controllers and be part of all $scopes (prototype inheritance magic)
//**attach in controller1:**
function MyCtrl1($rootScope) {
$rootScope.recs= { rec1 : "think philosophically" };
}
//**do nothing in controller for view2:**
function MyCtrl2($scope) {
//nothing
}
//**Markup for view2: automaticall makes use of data in $routeScope**
<p>Try doing this: {{recs.rec1 }}</p>
//**markup for view1 to respond to OPs question in comments**:
<input ng-model="recs.rec1" />
Update: Creating a custom service is a more scalable and structurally sound way to handle this, but the $rootScope method is the quick and dirty way.
Update2: added view1 markup to respond to OP question, edited example to take advantage of correct advice to use object rather than primitive.
Found the Solution to what I was looking for, The solution is in the Angular docs, here is the link http://docs.angularjs.org/cookbook/deeplinking.
Some part of the example on that link answers my question.
You should user $broadcast, $emit or scope communication. Try to avoid overloading the rootScope. It is as a bad practice as saving data into the application sessions.