Why is my AngularJS module never loaded? - angularjs

I am an AngularJS newbie, and am having difficulty getting an AngularJS form to work correctly. Chrome Dev Tools tells me my module is not being loaded.
Below is my html; it is a div within a Wordpress template:
<div ng-app="contact" style="float: left;">
<form method="post" name="form" role="form" ng-controller="ContactFormController" ng-submit="form.$valid && sendMessage(input)" novalidate>
<p ng-show="success">Thanks for getting in touch!</p>
<p ng-show="error">Something wrong happened!, please try again.</p>
<legend>Contact</legend>
<fieldset>
<div>
<label for="name">Name:</label>
<input type="text" id="name" name="name" ng-model="input.name" required>
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" ng-model="input.email" required>
</div>
<div>
<label for="messsage">Message:</label>
<textarea id="messsage" name="message" ng-model="input.message" required></textarea>
</div>
<div>
<label for="honeypot">I promise I'm not a bot</label>
<input type="text" id="honeypot" name="honeypot" ng-model="input.honeyPot">
</div>
</fieldset>
<button type="submit" name="submit" value="submit">Submit</button>
</form>
</div>
This is my angular code:
angular.module("contact", [])
.controller("ContactFormController", ['$scope', '$http', function($scope, $http) {
$scope.success = false;
$scope.error = false;
$scope.sendMessage = function( input ) {
$http({
method: 'POST',
url: 'http://alamanceforeducation.org/wp-content/themes/flex/library/scripts/processApplecartForm.php',
data: input,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.success( function(data) {
if ( data.success ) {
$scope.success = true;
} else {
$scope.error = true;
}
} );
}
}]);
The code is adapted from a tutorial. Can anyone help me out with what I am doing wrong?

There's nothing wrong with your code in terms of the problem you are having. The problem is the order in which you are loading the scripts.
The order should be:
1- angular.js
2- any-angular-dependency.js
3- your-angular-app.js
this is a working copy of your code
I'm not including the form because is just to show you that it doesn't find your angular module because either you are not including it or is not loading correctly from cdn, you might want to download it to have it locally and include the <script src="angular.js"></script> tag

In order to add a new module you need to make sure that:
The JS file is properly loaded on your page together with the other modules and angular.js
The module is properly declared for example: angular.module('myModule').directive(....) is not a module declaration, because doesn't have the dependencies array like this: angular.module('myModule',[]).directive(....)
Add the dependency on the declaration of your app, or add the module as dependency of other which already is a dependency of your app:
angular.module('app',['app.my-directives']).config(...)-
angular.module('app.my-directives',[]).directive('SomeDirective',function(){})
Here I have a full example of a working application using angular-ui-route (I recommend you this routeProvider instead of the default provider, it's more expressive and robust), I hope it works for you, it has 2 states each one with different views, and several modules for directives and factories:
Images Gallery with AngularJS
Images Gallery with AngularJS Live
PS: ignore the web.js file, it's only for deploy the dist folder using Node.JS
I hope this solve your issue, please update the question with the plunker

Related

how to catch nodejs api data in AngularJS page?

this is api code i am using and passing some parameters
app.get('/opner',function (req, res) {
res.sendFile(
path.join(__dirname, './','dist', 'index.html'),
{user: req.session.user,value1:req.session.value1}
);
});
i am serving angular with the same api.
in this case in ejs i can directly access this user and value1
with <%= user %> like this. but how to use the same in angular app
<div class="form-group">
<h4> value 1:</h4>
<textarea class="form-control" rows="8" ng-model="tx.data"></textarea>
</div>
<div class="form-group">
<h4>user:</h4>
<input class="form-control" type="text" ng-model="tx.user"/>
</div>
so i want to render this page with value1 and user values present.
so how to read and display in angular?
The node function res.sendFile is not the same as res.render.
res.render is for rendering EJS (or pug, or other pre-renderer).
res.sendFile only send file.
You cannot use the second argument of res.sendFile to send data alongside your index.html like you would do in EJS
The right way to do it would be to create another express route (like /getUser), and to send the json in this route with res.json({req.session.user,value1:req.session.value1})
You will then have to do a ajax request in Angular.
if you use Angular 1.x, I think the service name is http
for Angular 2+, the service name is HttpClient.
Once you have queryed the data, you can show it in your angular template like so:
<h4> value 1: {{tx.data}}</h4>
supposing you put your data on the $scope.tx.data object (angular 1.x) or as this.tx = {data : data, user : user} on the class of your component (angular 2+)
Like Felix says is better to make your own GET route to get the data via http request, but ifyou want to avoid that you need to use a template engine (like EJS or Pug) because Angular is loaded after template rendering.
res.render('yourPath/index.html', {user: req.session.user, value1: req.session.value1});
And in your AngularJS side you can use ng-init. EJS example:
<div class="form-group" ng-init="tx.data = '<%= value1 %>';tx.user = '<%= user %>'">
<h4> value 1:</h4>
<textarea class="form-control" rows="8" ng-model="tx.data"></textarea>
</div>
<div class="form-group">
<h4>user:</h4>
<input class="form-control" type="text" ng-model="tx.user"/>
</div>
PUG Interpolation example:
<div class="form-group" ng-init="tx.data = '!{value1}';tx.user = '!{user}">
<h4> value 1:</h4>
<textarea class="form-control" rows="8" ng-model="tx.data"></textarea>
</div>
<div class="form-group">
<h4>user:</h4>
<input class="form-control" type="text" ng-model="tx.user"/>
</div>

angular scope initialization sometimes empty

I'm working with angular 1.5 and a python/mongodb api.
The api is working fine (consistent and fast), but sometimes when I load a page with a form the data fields are empty.
The app uses ui.router to associate the chap state with the correct url and the chapController. I type that url into the address bar and hit return to load the page. In the controller, the path/to/api returns json data.
Here's a simplified version of the controller:
angular.module('configurer')
.controller('chapController', function($scope, $http, $state) {
var url='path/to/api';
$http.get(url).success(function(data){
$scope.data = data;
});
$scope.save = function()( {
$http.post(url, $scope.data).success(function() {
$state.go('home', {reload:true});
});
});
The view looks like this:
<button class="btn btn-primary" ng-click="save()">Save Changes</button>
<form>
<div class="row">
<div class="col-sm-3 form-group">
<label for="name">Name</label>
<input class="form-control" id="name" type="text" name="name" ng-model="data.chap.name" />
</div>
<div class="col-sm-9 form-group">
<label for="title">Title</label>
<input class="form-control" id="title" type="text" title="title" ng-model="data.chap.title" />
</div>
</div>
</form>
Usually the form comes up populated with data but sometimes the fields are blank (using the same url).
I can reload the page from the browser and then it will populate, but of course that's not a good user experience.
What am I doing wrong?
After research plus trial-and-error, I think I've got the answer. The reason the scope wasn't binding to the data is that there was no data: my server was sending a 304 "not modified" response.
So of course it couldn't bind with non-existent data but the http response was still counted as success. Seems like this would be a common 'gotcha'.
What worked for me is to add a config object to each http.get call, like this
http.get(url, {cache:true}).success(function(data) { etc...
My guess is that you could also set max-age and public on the http request headers so the server cannot respond with a 304. That didn't seem like the most efficient thing to do, so I went with using cache on the client so the server isn't even bothered.
This is working for me, but if problems pop up again, I'll repost.
Since you're using ui.router, I recommend using resolve for this.
Example:
$stateProvider
.state('chap', {
// ...
resolve: {
data: function($http){
return $http.get(...);
}
}
});
and in your controller:
angular
.module('configurer')
.controller('chapController', function(data, $scope, $http, $state) {
$scope.data = data;
}
Sometimes data won't bind with the scope. can you check by including this line
$scope.data = data;
$scope.$apply();
Inside success handler.
I am not sure, it may work. please try

Angular directive with custom / conditional actions

I have questions about Angular directives. The following is my code:
main controller & the directive:
<div ng-controller='ShopsController'>
<update-createform shop="shop" action='update()'></update-createform>
</div>
directive js:
(this way the direction action will take the 'action' input argument)
angular.module('app')
.directive('updateCreateform', function(){
return {
templateUrl: '/form.html',
restrict : 'E',
scope: {
shop: '=',
action: '&'
}
}
})
form.html template:
<form name="shopForm" ng-submit='action(shopForm.$valid)' novalidate>
<input type='text' name='name' required/>
<input type='text' name='description' required/>
</form>
ShopsController has a method:
exports.update = function(isValid) {
if (isValid) { /* update the shop*/ }
}
What I am doing is I am passing the shop data I get from the server, send it into the form so I can view and/or update the shop info.
It's also that I want to create shop info using the same form. In this case I just send in shop = [] and action='create()' instead.
My controller has an update method that takes the argument isValid. I don't know how to pass the directive shopForm.$valid outside and send it to server.
Two questions:
how do I get isValid variable from the directive?
Following Ari Lerner's ng-book: He said it's possible to do the following:
http://www.scribd.com/doc/215682987/NG-Book-The-Complete-Book-on-AngularJS-2013
instead of using directive above we use
<update-createform shop="shop" on-update='update()' on-create='create()'></update-createform>
and the directive 'action' will change to 'update' when shop is not empty otherwise action equals to 'create'? I tried his code but I cannot get it to work..
Any help would be greatly appreciated!
You can add an argument to action=update(isValid). This then gets resolved on the form submit.
So your html would look like this
<div ng-controller='ShopsController as shopCtrl'>
<update-createform shop="shop" action='shopCtrl.update(isValid)'></update-createform>
</div>
And your form would look like like this
<form name="shopForm" ng-submit='action({isValid:shopForm.$valid})' novalidate>
<input type='text' name='name' required/>
<input type='text' name='description' required/>
<button type="submit">Submit</button>
</form>
and controller would be
.controller('ShopsController', function() {
var exports = this;
exports.update = function(isValid) {
console.log(isValid)
if (isValid) { /* update the shop*/ }
}
})
http://plnkr.co/edit/Qh3HzKGnOo1NTP9Pfsmh?p=preview
OR
There's another way, although personally i find the syntax a little odd. Not that the first solution feels that intuitive either.
http://plnkr.co/edit/CRN9ruRekJiozJIBTe80?p=preview
Found that one in an excellent post about directives by Dan Wahlin
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters

Angular Form Validation not working at all

I have been trying to get form validation to work in my web app for a while now without any luck. So I tried to create a JSFiddle that works so I can then copy the code directly back to my app. However, I copied the code directly from the AngularJS Forms page into the JSFiddle and it does not work... I have included the newest angular.min.js file into the fiddle. Can someone please let me know what I am doing wrong?
HTML
<div ng-controller="Controller">
<form name="form" class="css-form" novalidate>
Name:
<input type="text" ng-model="user.name" name="uName" required /><br />
E-mail:
<input type="email" ng-model="user.email" name="uEmail" required/><br />
<div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:
<span ng-show="form.uEmail.$error.required">Tell us your email.</span>
<span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
</div>
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<input type="checkbox" ng-model="user.agree" name="userAgree" required />
I agree: <input ng-show="user.agree" type="text" ng-model="user.agreeSign"
required /><br />
<div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
<button ng-click="reset()" ng-disabled="isUnchanged(user)">RESET</button>
<button ng-click="update(user)"
ng-disabled="form.$invalid || isUnchanged(user)">SAVE</button>
</form>
</div>
JS
var app = angular.module('myapp', []);
function Controller($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
Looks like you are missing ng-app="myapp"
I cannot get this to work in JSFiddle either, but in my test app (VS 2013 with Angular 1.2.18) it works with this small change:
app.controller('Controller', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
});
Fixed it without having to change your controller code or anything else. There are some issues with including the right library and taking the basic steps to run an Angular app, which makes this a good lesson in environment checking.
Namely: You forgot to include the Angular library in the jsfiddle and, I suppose, in your own environment. If you include it and add add in a ng-app="myapp" wrapper for Angular to find, it works just fine.
Here's the updated, working jsfiddle
Problems like these can be really frustrating—I understand and have been in a situation many times where the logic of my code seems to work perfectly and I find out some library wasn't being included or that a basic need wasn't being filled. I would recommend always double checking your 'surroundings', or the environment that your code exists in. Make sure libraries are being served, there aren't any CDN issues, and that there aren't any typos throwing the inclusions off.
Hope this helps!
PS: when copying example code from a really big and well-developed project like angular, the first thought you should have if it doesn't work is that there's something in your environment that's throwing it off, since the team behind Angular and projects like it is extremely unlikely to have put faulty example code out. It happens, but it's more unlikely than there being a problem with the local environment.

AngularJS and nested forms: Correct way of naming and declaring model

Ok, so I am creating a form like so:
<form novalidate class="simple-form" action="" name="mainForm" ng-submit="doSubmit()" method="POST">
<div ng-form name="giftForm" class="panel-body">
<input type="text"
id="x_amount"
name="x_amount"
class="form-control input-lg"
ng-model="giftForm.amount"
ng-required="true">
</div>
<div class="row">
<button type="submit" class="btn" ng-disabled="mainForm.$invalid">Submit</button>
</div>
</form>
This works for validation, i.e. that mainForm.$invalid only highlights enables the button after the input has text. However, using batarang, I noticed that the scope looks like so:
{"giftForm":{"x_amount":{},"amount":"a"}}
So it is creating model values based on the name and the declared ng-model. If I change them to be the same like so:
<input type="text"
id="x_amount"
name="x_amount"
class="form-control input-lg"
ng-model="giftForm.x_amount"
ng-required="true">
The submit shows the correct scope of:
{"giftForm":{"x_amount":"a"}}
But the input field initially shows with [Object object] in the input, which makes me think I am confusing something here..... I can't have that in all of the input fields.
I'd like the name and the model to be the same. That would seem to be the progressive enhancement way and would allow a normal non-ajax post by simply removing the ng-submit method and the ajax way would look like:
$http({
method : 'POST',
url : 'formAction.do',
data : $.param(angular.toJson($scope.mainForm)),
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.success(function(data) {
//success
})
.error(function(data, status, headers, config) {
//error
});
Anybody has insight into what I am missing or if my architecture is flawed from the ground-up, I'd appreciate the wisdom....
I'd like the name and the model to be the same.
You could do that, but you'd have to have a separate scope, and therefor a separate controller for your form.
More importantly, though, this isn't going to buy you anything. The input name attributes are primarily used for validation display, and not much else.
Your use of $http concerns me more. It looks like you're thinking in a JQuery mindset. I'd challenge you to throw JQuery out the window for a while until you get used to Angular.
Here's what people generally do with forms (From the model structure to the naming and validation):
View:
<form name="myForm" ng-submit="sendFoo()">
<div>
<label for="name">name</label>
<input type="text" id="name" name="name" ng-model="foo.name" required/>
<span ng-show="myForm.name.$error.required">required</span>
</div>
<div>
<label for="email">email</label>
<input type="email" id="email" name="email" ng-model="foo.email" required/>
<span ng-show="myForm.email.$error.required">required</span>
<span ng-show="myForm.email.$error.email">invalid email</span>
</div>
<button type="submit" ng-disabled="myForm.$invalid">Submit</div>
</form>
Controller:
app.controller('MyCtrl', function($scope, $http) {
$scope.foo = {
name: 'Someone Special',
email: 'test#monkey.com'
};
$scope.sendFoo = function (){
$http.post('/Some/Url/Here', $scope.foo)
.then(function(result) {
$scope.result = result.data;
});
});
});
You'll notice that the name of the form and the names of the inputs are only used for validation on those <span> tags. Like so: <span ng-show="[formName].[fieldName].$error.[validationName]">invalid message</span>. That object is available on the $scope at $scope.formName, but there usually isn't a reason to access it directly in your controller.
I hope this helps you (or someone).
Naming a form places a variable in scope with that name. Under it, it puts properties named after the form fields names. However, you already have a model in the scope with the same name as the form: giftForm. This causes confusion: the template overwrites the model and/or vice versa.
So, give another name to one of them, eg name the model giftModel.

Resources