I am trying to use the ng-template directive in my code to be able to show a div after a button click event but I cannot get it to work since I need to have the angular/common library. I tried to reference it by adding a script tag
<script src="https://cdn.jsdelivr.net/npm/#angular/common#11.0.2/bundles/common.umd.min.js" integrity="sha256-+HBVhNZwWCgkN0Z0tvWyjqjm+yI9F/szNt3Yz4/0/ws=" crossorigin="anonymous"></script>
But every time I test my app, the following error appears in the console.
common.umd.min.js:35 Uncaught TypeError: Cannot read property 'InjectionToken' of undefined
I am stuck and don't know how can I be able to use the ng-template directive
HTML (index.html):
<ng-template>
<div class="container">
<h2>Edit or Delete an Evangelist</h2>
<form name="userEditForm">
<p>person id: <input type="text" id="name" ng-model="userEdit.personid" disabled /></p>
<p>name: <input type="text" id="name" ng-model="userEdit.name" /></p>
<p>location: <input type="text" id="location" ng-model="userEdit.location" /></p>
<button id="btn-edit-evangelist" class="btn btn-primary" ng-click="editName(userEdit)">Save</button>
<button id="btn-canceledit-evangelist" class="btn btn-default btn" ng-click="delName(userEdit);">Delete User</button>
</form>
</div>
<div *ngIf="isEdit">
</div>
</ng-template>
Angular (main-app.js):
"use strict";
angular.module('MainApp', [
])
.controller("MainController", function ($scope, $http) {
//initialize scope variables
$scope.user = {
name: function (theName) {
if (angular.isDefined(theName)) {
$scope._name = theName;
}
return $scope._name;
}(),
location: function (theLocation) {
if (angular.isDefined(theLocation)) {
$scope._location = theLocation;
}
return $scope._location;
}()
};
function redirectToEdit(user) {
this.isEdit = !this.isEdit;
var id = user.personid;
$http.get('https://webapimongodb.herokuapp.com/api/name/' + id, {
params: { personid: user.personid, name: user.name, location: user.location },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
})
.success(function (res) {
console.log(res);
$scope.userEdit.personid = res.personid;
$scope.userEdit.name = res.Name;
$scope.userEdit.location = res.Location;
});
}
})
Will it be possible to have the #angular/common module referenced via a script tag or do I need to have it referenced via NPM?
I think the issue here is the version being used.
The code you provided is written in Angular.js code and #angular/common is an Angular module
To get your code working you need this instead
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.0/angular.min.js"></script>
Here you can find the Angular.js docs, which, by the way, is deprecated.
And this article explains the difference among Angular and Angular.js
Related
I'm building a silly little calculator in an attempt to learn AngularJS. I'm attempting to use ng-click trigger events to update the "screen" of my calculator. Here's my code:
var calcApp = angular.module('NodeCalc', []);
calcApp.controller('CalcController', ['$scope', function ($scope) {
$scope.memory = {
recall: function() {
console.log('memory recall');
},
clear: function() {
console.log('memory clear');
},
add: function(value) {
console.log('memory add');
}
}
$scope.buttons = {
memory: [
{text: 'mrc', action: $scope.memory.recall},
{text: 'm-', action: $scope.memory.clear},
{text: 'm+', action: $scope.memory.add},
]
};
}]);
<body ng-app="NodeCalc" ng-controller="CalcController">
<form class="calc">
<p class="calc-display">
<input type="text" name="res" id="res" value="0" class="calc-display-input" onfocus="this.blur()">
</p>
<p class="calc-row">
<button ng-repeat="button in buttons.memory" type="button" class="calc-button calc-button-gray" ng-click="{{button.action}}">{{button.text}}</button>
<button type="button" class="calc-button calc-button-red calc-button-big" onclick="a('/')">/</button>
</p>
So, I know it has to do with the way I'm attaching my memory functions to my scope object. Can I not use scope in this way on the ng-click directive? I'm not really sure how else to achieve my goal here. The buttons render correctly, but I get a huge angular error-barf in my console related to:
Error: [$parse:syntax] http://errors.angularjs.org/1.5.8/$parse/syntax?p0=%7B&p1=invalid%20key&p2=2&p3=%7B%7Bbutton.action%7D%7D&p4=%7Bbutton.action%7D%7D
ng-click expression should be ng-click="button.action()"
While using ng-* directive, one is not suppose to wrap it with mustache, passed expression will be parsed by angular
var calcApp = angular.module('NodeCalc', []);
calcApp.controller('CalcController', ['$scope',
function($scope) {
$scope.memory = {
recall: function() {
console.log('memory recall');
},
clear: function() {
console.log('memory clear');
},
add: function(value) {
console.log('memory add');
}
}
$scope.buttons = {
memory: [{
text: 'mrc',
action: $scope.memory.recall
}, {
text: 'm-',
action: $scope.memory.clear
}, {
text: 'm+',
action: $scope.memory.add
}, ]
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="NodeCalc" ng-controller="CalcController">
<form class="calc">
<p class="calc-display">
<input type="text" name="res" id="res" value="0" class="calc-display-input" onfocus="this.blur()">
</p>
<p class="calc-row">
<button ng-repeat="button in buttons.memory" type="button" class="calc-button calc-button-gray" ng-click="button.action()">{{button.text}}</button>
<button type="button" class="calc-button calc-button-red calc-button-big" onclick="alert('/')">/</button>
</p>
One idea is just calling a function defined on $scope in the ng-click (the normal way) and passing the $index from the ng-repeat.
ng-click="clicked($index)"
$scope.clicked = function(index) {
var fn = $scope.buttons.memory[index].action;
fn();
}
I am currently working on a small angularjs app which is basically a user profile management app.
The problem i am having is with adding users dynamically. When i enter the user data, it successfully POST's to my local server i have setup, BUT i have to refresh the page to see the new user in the users list
I obviously dont want to have to refresh.
-Yes i've tried $scope.apply() after running the POST function
Something i am noticing with Angular Batarang (Debugging tool), is that the scope is updating fine, but there is a blank spot or 'null' value where the new user should be.
Here are the Controllers:
UsersApp.controller('UserListController', [ '$scope', 'userService', function($scope, userService) {
$scope.usersList = userService.usersList;
$scope.users = userService.users;
$scope.user = userService.user;
}]);
UsersApp.controller('AddUserController', function($scope, $window, dataResources, userService) {
$scope.addNew = function addNew(newUser) {
$scope.usersList = userService.usersList;
var firstName = newUser.firstName;
var lastName = newUser.lastName;
var phone = newUser.phone;
var email = newUser.email;
$scope.newUserData = {
firstName , lastName, phone , email
}
new dataResources.create($scope.newUserData);
$scope.usersList.push(dataResources);
$scope.$apply();
};
And Here are my views:
Add User:
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script src="js/minimize.js"></script>
<div ng-controller="AddUserController">
<div class="userInfo" id="usernameDiv">
<h2 id="username">User<img id="showhide" src="images/plus.png" style="position:absolute; padding-left:15px; width:31px; color:white;"></h2>
</div>
<div class="userInfo">
<div id="listInfo">
<form ng-controller="AddUserController">
<input type="text" placeholder= "First Name" ng-model="newUser.firstName"></input>
<input type="text" placeholder= "Last Name" ng-model="newUser.lastName"></input>
<input type="text" placeholder= "Phone Number" ng-model="newUser.phone"></input>
<input type="text" placeholder= "Email" ng-model="newUser.email"></input>
<button type="submit" ng-click="addNew(newUser)">Add User</button>
</form>
</div>
</div>
Users List:
<!DOCTYPE html>
<html>
<head></head>
<body id="">
<div ng-controller="UserListController">
<div class="userInfo">
<h2>List of Users</h2>
<div id="listInfo">
<ul style="list-style-type: none;">
<li ng-repeat="user in usersList">
<!--<p class="userData">ID: {{ user }}</p> -->
<p class="userData"><a style="cursor:pointer;" ui-sref="UserProfile">{{ user.firstName }}</a></p>
</li>
</ul>
</div>
</div>
Factory and Service:
UsersApp.factory('dataResources', [ '$resource', function($resource) {
return $resource('http://localhost:24149/users/:id', {}, {
query: {method:'GET', params:{idnum: '#id'}, isArray:true},
create: {method:'POST', headers: { 'Content-Type': 'application/json' }},
update: {method:'PUT', params:{idnum: '#id'}},
remove: {method:'DELETE', params:{idnum:'#id'}, isArray:true}
});
}]);
UsersApp.service('userService', function(dataResources) {
return {
usersList: dataResources.query()
}
});
I'm not sure if I follow exactly, but I believe you need to deal with a promise from your POST and then push the result. e.g.,
dataResources.create($scope.newUserData).$promise.then(function(data) {
$scope.usersList.push(data);
});
Your service will return a promise and then when the POST is complete your service should return the new user and you just add it to your current list.
See $resource documentation:
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
According to the doc your code should look like this:
dataResources.create($scope.newUserData,
function(data) {
$scope.usersList.push(data);
}
);
controller: you don't need to make a new userdata object, you can just use newUser
UsersApp.controller('AddUserController', function($scope, $window, dataResources, userService) {
$scope.usersList = userService.usersList;
$scope.addNew = function addNew(newUser) {
dataResources.create($scope.newUser,
function(data) {
$scope.usersList.push(data);
}
);
};
};
Same idea for angular2 using observables.
public posts: any;
onPost(input) {
this.dataService.jsonserverPost(input)
.subscribe(
(data: any) => {
this.posts.push(data);
}
);
}
Ive built a rest-API to add todos in a mongodb. I can successfully save instances by using the following setup in postman:
http://localhost:3000/api/addtodo x-www-form-urlencoded with values text="Test", completed: "false".
Now when I try to replicate this with Angular, it doesnt work, the todo is saved but without the text and completed attributes, I cant seem to access the text or completed values from body. What am I doing wrong? Code below:
Angular-HTML:
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">
<!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
<input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text">
</div>
<!-- createToDo() WILL CREATE NEW TODOS -->
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
Angular-js:
$scope.createTodo = function() {
$http.post('/api//addtodo', $scope.formData)
.success(function(data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
REST-API:
router.post('/addtodo', function(req,res) {
var Todo = require('../models/Todo.js');
var todo = new Todo();
todo.text = req.body.text;
todo.completed = req.body.completed;
todo.save(function (err) {
if(!err) {
return console.log("created");
} else {
return console.log(err);
}
});
return res.send(todo);
});
$http.post sends it's data using application/json and not application/x-www-form-urlencoded. Source.
If you're using body-parser, make sure you've included the JSON middleware.
app.use(bodyParser.json());
Either that or change your default headers for angular.
module.run(function($http) {
$http.defaults.headers.post = 'application/x-www-form-urlencoded';
});
Typically to validate a form in Angular, I would use something like this on the ng-submit directive:
<form name="formName" ng-submit="formName.$valid && submitForm()"></form>
This works great when the form has a name that I set myself while building the form. However, in my current situation, I am trying to create multiple forms based on a list of objects. In this case, each form has a name that is determined on the fly.
When the user submits one of these forms, how can I validate it before running the submitForm() function for that form?
Here's a jsfiddle of the simplified problem: http://jsfiddle.net/flyingL123/ub6wLewc/1/
My question is, how can I access the name of the form in order to validate it? Here is the code from the fiddle:
var app = angular.module('app', []);
app.controller("AppController", ['$scope', function($scope) {
$scope.forms = [{
id: 1,
value: "val1"
}, {
id: 2,
value: "val2"
}, {
id: 3,
value: "val3"
}];
$scope.submitForm = function() {
alert('submitted');
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div id="app" ng-app="app" ng-controller="AppController">
<div class="formWrapper" ng-repeat="form in forms">
<form name="{{ 'form' + form.id }}" ng-submit="submitForm()" novalidate>
<input ng-model="form.value" required />
<button type="submit">Submit</button>
</form>
</div>
</div>
You can always use this to access the scope in your templates.
{{this.foo === foo}} <!-- This will always show "true" -->
Therefore, you can simply use this[myDynamicFormName] to access the form:
<form name="{{'form' + form.id}}" ng-submit="this['form' + form.id].$valid && submitForm()"></form>
Back again with a new type error. Working on authentication right now. Working with AngularJS and firebase. Right now when I run my function on click of the submit button I get this in my console "TypeError: this.mRef.auth is not a function". I'm thinking it's something simple but here is my login controller:
.controller('Login', ['$scope', 'angularFire',
function($scope, angularFire) {
$scope.signin = function(){
var ref = "https://myappurl.firebaseio.com";
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
// user authenticated with Firebase
console.log(user);
} else if (error) {
// an error occurred authenticating the user
console.log(error);
} else {
// user is logged out
console.log("hello");
}
});
console.log($scope);
var user = $scope.cred.user;
var pass = $scope.cred.password;
auth.login('password', {
email: user,
password: pass,
rememberMe: false
});
}
}])
Next is the html. I have it inside a controller called login and here is what is in it:
<div class="inner loginbox" ng-controler="Login"
<fieldset>
<label class ="white">Username</label>
<input type="text" id="username" ng-model="cred.user">
<span class="help-block"></span>
<label class ="white">Password</label>
<input type="password" id="password" ng-model="cred.password">
<div class="centerit rem-me">
<label class="checkbox">
<div class="white">Remember me?
<input type="checkbox" ng-model="cred.remember">
</div>
</label>
</div>
<div class="spacer1">
</div>
<a class="btn btn-inverse btn-large btn-width" id="signupsubmit" ng-click="signin()">Sign in</a>
</fieldset>
</div>
The type error I get refers to firebase-auth-client.js on line 79. In chrome I have this in the console: Uncaught TypeError: Object https://kingpinapp.firebaseio.com has no method 'auth'
When instantiating the FirebaseAuthClient, you should pass an actual Firebase reference, not just the string representation of one.
Updating your code to use the following snippet should fix your problem:
var ref = new Firebase("https://myappurl.firebaseio.com");
var auth = new FirebaseAuthClient(ref, function(error, user) {