Angularjs edit and save - javascript

If been working on this form, that can change the name and mail of the item.
But when I looked at this link https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#services , I saw I made some mistakes in the style but now it doesn't work anymore.
I actually really don't know why. It shows the {{vm.name}} and {{vm.email}} but not the name, also It doesn't hide the input and the buttons who show up when you click on the edit button.
this is the link from plunker https://embed.plnkr.co/yqUsSkwNBPBfOQS5jm5l/ .
angular
.module("form",[])
.controller("LocationFormCtrl", LocationFormCtrl);
function LocationFormCtrl(){
var vm = this;
vm.name = 'henk';
vm.mail = 'gmail';
vm.editorEnabled = false;
var service = {
name: name,
mail : mail,
enableEditor : enableEditor,
editorEnabled: editorEnabled,
disableEditor: disableEditor,
save: save
};
return service;
function enableEditor(){
vm.editorEnabled = true;
vm.editName = vm.name;
vm.editMail = vm.email;
}
function save(){
vm.name = vm.editName;
vm.email = vm.editMail;
disableEditor();
}
function disableEditor(){
vm.editorEnabled = false;
}
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="form" ng-controller="LocationFormCtrl">
<div ng-hide="editorEnabled">
{{ vm.name }}
{{ vm.email }}
<div ng-click="enableEditor()" style="border-radius:50%; background-color:black; height:35px; width:35px;">
<i class="fa fa-pencil-square-o" aria-hidden="true" style="color:white;margin-left:11px; margin-top:10px;"></i>
</div>
</div>
<div ng-show="editorEnabled">
<label>Name:</label>
<input type="text" ng-model="vm.editName" ng-show="editorEnabled">
<br><br>
<label>Email:</label>
<input type="text" ng-model="vm.editMail" ng-show="editorEnabled">
<div ng-click="save()" style="border-radius:50%; background-color:black; height:35px;width:35px;" >
<i class="fa fa-floppy-o" aria-hidden="true" style="color:white; margin-left:11px; margin-top:10px;"></i>
</div>
<div ng-click="disableEditor()" style="border-radius:50%; background-color:black;height:35px; width:35px;">
<i class="fa fa-ban" aria-hidden="true" style="color:white; margin-left:11px; margin-top:10px;"></i>
</div>
</div>
</body>
</html>

its because the reference was taken of controller in ng-controller as you can see,
its john papa Structure.
For more information you can check.
https://github.com/johnpapa/angular-styleguide

Either you use this syntax of angular controller to avoid $scope, or just use $scope.
I corrected your plunker, you have to use as syntax in html view and bind all data to this object in controller.
Please notice below points in plunker :
ng-controller="LocationFormCtrl as vm"
In html bind everything to vm, like ng-click="vm.save()".
In controller bind everything to this, or its alias.. like vm.enableEditor = function (){/\\
and If you want to do it with $scope way, then see this $sope Plunker

Related

To change the icon upon click with angularJs

Here is the Html displaying only one icon now, but what I want is that whenever that edit icon is being clicked it changes to save icon immediately.
Below is the html:
<td style="padding:5px!important;">
<i class="fa fa-edit" ng-click="updateEmp()">
</td>
And down below is the JS file, is there any way to add the html bind to the JS File?
JS Code:
$scope.updateEmp = function (){
$scope.isReadonly = false;
console.log("update Employee");
}
You can use ng-class and toggle the class on click as follows.
ng-class="{'fa fa-save' : toggle, 'fa fa-edit' : !toggle}"
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope){
$scope.updateEmp = function (){
$scope.toggle = !$scope.toggle;
}
});
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<h1 style="padding:5px!important;">
<i ng-class="{'fa fa-save' : toggle, 'fa fa-edit' : !toggle}" ng-click="updateEmp()"></i>
</h1>
</div>

Remove a range on table with JS

I am trying to remove a range on my table. Here is my HTML code:
<td ><button id="btnRemoveRange" class="pull-left btn btn-xs btn-success" ng-click="removeRange(this)"><i class="fa fa-minus" aria-hidden="true"></i></button></td>
And my JS function is this:
$scope.removeRange = function(obj){
obj.parentNode.parentNode.style.display='none';
}
But it is not working.
I tried using Span and it worked with this code:
<td><span onclick="this.parentNode.parentNode.style.display = 'none';">x</span></td>
Can you please tell me what did I do wrong in the first code?
Thanks
Use angular.element().css() like the following:
var myApp = angular.module('myApp', []);
myApp.controller('myController', function($scope){
$scope.removeRange = function(obj){
var el = angular.element(document.querySelector( '#btnRemoveRange')).parent();
//console.log(el);
el.css('display','none');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div ng-app="myApp" ng-controller="myController">
<div><td><button id="btnRemoveRange" class="pull-left btn btn-xs btn-success" ng-click="removeRange(this)"><i class="fa fa-minus" aria-hidden="true"></i>Click</button></td></div>
</div>
Try to debug it with alert();, I'm not sure whether the function has been executed.
Also it is a best practice to determine whether the element exists - in order to prevent JS errors.
$scope.removeRange = function(obj){
alert("Something is happening?");
if (obj.parentNode.parentNode)
obj.parentNode.parentNode.style.display='none';
return false;
}
Another option is to use a raw javascript and define "function removeRange(obj)":
<button id="btnRemoveRange" ... onclick="return removeRange(this)">

Angular Clicking on Text to show div tag

I was wondering how to accomplish this with Angular as it seems that ng-click is something to use, then ng-model seems like that could be used.
I want to click on Text and then have a div show its contents and it is not working
My fiddle https://jsfiddle.net/gdxwtoL7/
<div class="well" ng-controller="MyController">
<a class="btn btn-primary" ng-model="selMe" ng-click="handleAnchorClick()">Enter Address</a>
</div>
<br>
<br>
<div ng-if="selMe">
adfadf
</div>
simple module and controller
angular.module('myapp', []);
angular.module('myapp').controller('MyController', MyController)
function MyController($scope) {
}
You're not doing anything inside the ng-click function, and you have the ng-if outside of the controller linked to the variable inside it.
https://jsfiddle.net/gdxwtoL7/1/
HTML
<div class="well" ng-controller="MyController">
<a class="btn btn-primary" ng-click="handleAnchorClick()">Enter Address</a>
<br>
<br>
<div ng-if="selMe">
adfadf
</div>
</div>
JS
angular.module('myapp', []);
angular.module('myapp').controller('MyController', MyController)
function MyController($scope) {
$scope.handleAnchorClick = function () {
$scope.selMe = true
}
}
The controller has to be aware of the div you want it to show.
the ng-if is waiting for the value of the selme which you can alter from the controller.
The ng-model binds your data to your controller in adding two-way data binding.
I made a little enhancement to your code to toggle the div when the text is clicked multiple times.
https://jsfiddle.net/gdxwtoL7/2/
<div class="well" ng-controller="MyController">
<a class="btn btn-primary" ng-model="selMe" ng-click="handleAnchorClick(selMe)">Enter Address</a>
<br>
<br>
<div ng-if="selMe">
adfadf
</div>
</div>
angular.module('myapp', []);
angular.module('myapp').controller('MyController', MyController)
function MyController($scope) {
$scope.handleAnchorClick = function (selMe) {
$scope.selMe = !selMe
}
}
The ngModel directive binds an input,select, textarea (or > custom form control) to a property on the scope using NgModelController, which is created and exposed by this directive.
ngModel is responsible for:
Binding the view into the model, which other directives such as input, textarea or select require.
Providing validation behavior (i.e. required, number, email, url).
Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
Setting related css classes on the element (ng-valid, ng-invalid, ng-dirty, ng-pristine, ng-touched, ng-untouched, ng-empty, ng-not-empty) including animations.
Registering the control with its parent form.
The ngClick directive allows you to specify custom behavior when an element is clicked.
Note : we need ng-click to capture the event and manipulate the data stored in ng-model.
Here is simple code without the need of controller:
<div class="well">
<a class="btn btn-primary" href="" ng-click="show=true">Enter Address</a>
</div>
<br>
<br>
<div ng-show="show">
adfadf
</div>
As #MikeHughesIII already pointed out, outside of your controller you can't reach $scope variables.
I am adding a quick snippet made after Mike's answer for completeness sake, showing a show/hide (toggle) approach, where the function sets the visibility variable to the opposite of its current status (true or false) when the function is invoked.
Hope that helps to clarify the issue.
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="myController">
<h1>Hello {{hello}}!</h1>
<a href ng-click="toggleDivVisibility()">Enter your address</a>
<br>
<textarea ng-if="visible" name="address" id="address" cols="30" rows="5"></textarea>
</div>
<script>
angular.module('myApp', []);
angular.module('myApp')
.controller('myController', myController);
function myController($scope) {
$scope.hello = "world";
$scope.visible = false;
$scope.toggleDivVisibility = function() {
$scope.hello = 'mondo';
$scope.visible = !$scope.visible;
}
}
</script>
</body>
</html>

AngularJS view not updating

I'm trying to make my first AngularJS application and I've run into a problem.
I have an input:
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
A button:
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
and an expression:
{{ activeUser }}
I want the text to change to whatever was typed in the input once the button is clicked. For that I have the following controller:
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userNameLogin = "";
$scope.activeUser = "Test";
$scope.setActiveUser = function() {
$scope.activeUser = $scope.userNameLogin;
console.log($scope.activeUser);
};
}]);
The initial value "Test" is shown just fine and according to the console the value of "activeUser" is being changed correctly as well. But the text in the view stays the same.
I have seen similar questions where a $scope.$apply() was the answer, but if I add that after the console.log I get
"Error: [$rootScope:inprog] $apply already in progress".
What am I missing here?
EDIT:
I have noticed that If I put the input, button and expression in the same HTML file it all works fine. However my Input and button are in a navbar in index.html while the expression is in view1.html
This is the body of index.html:
<body ng-app="myApp.view1">
<nav class="navbar navbar-inverse navbar-fixed-top" ng-controller="View1Ctrl as view">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#/view1">Kwetter</a>
</div>
<div class="navbar-collapse collapse" >
<ul class="nav navbar-nav">
<li>Home</li>
<li>Profile</li>
</ul>
<form class="navbar-form navbar-right">
<div class="form-group">
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
</div>
<div class="form-group">
<input type="password" placeholder="password" class="form-control">
</div>
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
</form>
</div>
</div>
</nav>
<div id="pagewrapper" class="container">
<div ng-view></div>
<div>Angular seed app: v<span app-version></span></div>
</div>
and this is my view1.html
<div ng-controller="View1Ctrl as view">
<!-- row 1: welcome -->
<div class="row">
<div class="col-md-12 pull-left">
<image ng-src="{{ view.users[0].avatar }}"/>
<!-- If I put the button and input here it will work -->
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
{{ activeUser }}
</div>
</div>
<!-- row 2: main content -->
<!-- left the rest of the content out because it would just clutter the page -->
I tried placing the ng-controller in <div id="pagewrapper" class="container"> instead of the first div of view1.html, but that made no difference.
I think u have misplaced the button or textbox or expression,
note : these should be inside the ng-controller.
please try this, it will work
<html>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-beta.6" src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="View1Ctrl">
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
{{activeUser}}
</div>
<h1>Hello Plunker!</h1>
</body>
</html>
script.js code
var app = angular.module("app",[]);
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userNameLogin = "";
$scope.activeUser = "Test";
$scope.setActiveUser = function() {
$scope.activeUser = $scope.userNameLogin;
console.log($scope.activeUser);
};
}]);
refer http://plnkr.co/edit/ixbByBQ9nGm4XEqEFi4t?p=preview
You have the properties directly on $scope and that is breaking the binding. Instead try:
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userInfo = {
userNameLogin: "",
activeUser:"Test"
}
$scope.setActiveUser = function() {
$scope.uesrInfo.activeUser = $scope.userInfo.userNameLogin;
console.log($scope.activeUser);
};
}]);
and in your view:
{{userInfo.activeUser}}
From Egghead.io https://egghead.io/lessons/angularjs-the-dot
Within your code I can't see anything causing the problem. I made a fiddle, that shows that your code works:
http://jsfiddle.net/xxvsn8xs/
You need to declare the ng-appand the ng-controller of course, like in the fiddle, to let the app work at all.
Also, an view update might not occur, if setting the activeUser actually occurs outside of the angular scope, which might be within an external library or whatever. It is true, that these could be achieved by calling $scope.$apply() directly, but it is nor recommended, as the digest might already be in progress. This is the case in your code, as why you get the according error message.
Instead use angulars $timeout service with a callback and 0 delay, that applies the value to $scope.activeUser. $timeout will check, if a digest cycle is in progress and if not, will start one.
$scope.setActiveUser = function() {
$timeout(function () {
$scope.activeUser = $scope.userNameLogin;
console.log($scope.activeUser);
});
};
Don't forget to define $timeout in your controllers dependencies:
app.controller('View1Ctrl', ['$scope', '$timeout', function($scope, $timeout) {
Angular watches the variable you bind to $scope, but if you replace that variable Angular is not able to detect it. That's why $apply would be a suggestion.
Another suggestion is to bind the variable to a 'model' variable:
app.controller('View1Ctrl', ['$scope', function($scope) {
$scope.userNameLogin = "";
$scope.myData = { activeUser: "Test" };
$scope.setActiveUser = function() {
// Angular will pick up the change in the myData object, and will update all variables attached to it
$scope.myData.activeUser = $scope.userNameLogin;
console.log($scope.myData.activeUser);
};
}]);
view:
{{ myData.activeUser }}
Do you execute your application in Apache ? I'd the same issue when I was using file:// And I fixed my issue by using a localhost.
I put my navbar (containing the input and button) in a partial and made a new directive for it. Instead of placing the navbar in the index.html I put it in the individual partials and now it works fine. I suspect the problem had something to do with different scopes.
navbar html:
<a class="navbar-brand" href="#/view1">
Kwetter
<image id="navbar-image" src="src/kwetter_logo.png"/>
</a>
</div>
<div class="navbar-collapse collapse" >
<ul class="nav navbar-nav">
<li>Home</li>
<li>Profile</li>
</ul>
<form class="navbar-form navbar-right">
<div class="form-group">
<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
</div>
<div class="form-group">
<input type="password" placeholder="password" class="form-control">
</div>
<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
</form>
</div>
</div>
the directive:
app.directive('navbar', function() {
return {
restrict: 'E',
templateUrl: 'partials/navbar.html',
controller: 'View1Ctrl as view'
}
});
Then I just added <navbar></navbar> to every view where I want a navbar.
Thanks everyone, your help pushed me in the right direction.

Ember -retrieving data from server to a view?

Does anyone happen to know How to show data from server, right now ive been showing related models in basic handlebars like this
{{
view Ember.Select
prompt="Organization"
contentBinding="organizations"
optionValuePath="content.id"
optionLabelPath="content.name"
selectionBinding="selectedOrganization"
}}
But i need to create an has many form... which im duplicating using views? Is using views even the right path to go ?!
{{#each view.anotherField}}
{{view Ember.TextField value=view.name}}
{{/each}}
Here is the output of my form, u can see Organizatons form being doubled
JSbin http://jsbin.com/efeReDer/7/edit
Today I came up with this... :D Kinda serves the purpose ? looks ugly tho
http://emberjs.jsbin.com/acUCocu/6/edit
Basically i made an empty model which i then each loop.
On action i "store.create".empty record to it.
Give me your thoughts on this :)
Also is there a way to make these fields indepedent ? without all changing their content while an input is changed.
Cheers,
kristjan
Here you can find an example to work on, of what i think you are asking
http://emberjs.jsbin.com/iPeHuNA/1/edit
js
Tried to separate the entities related to the model of the app, from how they will be displayed.Created an ember class App.Person that will hold the data from server. I have not used ember-data, but it is quite easy to replace the classes with ember-data notation and the dummy ajax calls with respective store calls etc, if desired.
App = Ember.Application.create();
App.Router.map(function() {
this.route("persons");
});
App.IndexRoute = Ember.Route.extend({
beforeModel: function() {
this.transitionTo("persons");
}
});
App.PersonsRoute = Ember.Route.extend({
model:function(){
return $.ajax({url:"/"}).then(function(){/*in url it is required to place the actual server address that will return data e.g. from a rest web service*/
/*let's imagine that the following data has been returned from the server*/
/*i.e. two Person entities have already been stored to the server and now are retrieved to display*/
var personsData = [];
var person1 = App.Person.create({id:1,fname:"Person1",lname:"First",genderId:2});
var person2 = App.Person.create({id:2,fname:"Person2",lname:"Second",genderId:1});
personsData.pushObject(person1);
personsData.pushObject(person2);
return personsData;
});
},
setupController:function(controller,model){
/*this could also be retrieved from server*/
/*let's mimic a call*/
$.ajax({url:"/",success:function(){
/*This will run async but ember's binding will preper everything.If this is not acceptable, then initialization of lists' values/dictionary values can take place in any earlier phase of the app. */
var gendersData = [];
gendersData.pushObject(App.Gender.create({id:1,type:"male"}));
gendersData.pushObject(App.Gender.create({id:2,type:"female"}));
controller.set("genders",gendersData);
model.forEach(function(person){
person.set("gender",gendersData.findBy("id",person.get("genderId")));
});
}});
controller.set("model",model);
}
});
App.PersonsController = Ember.ArrayController.extend({
genders:[],
actions:{
addPerson:function(){
this.get("model").pushObject(App.Person.create({id:Date.now(),fname:"",lname:""}));
},
print:function(){
console.log(this.get("model"));
}
}
});
App.PersonFormView = Ember.View.extend({
templateName:"personForm",
/*layoutName:"simple-row"*/
layoutName:"collapsible-row"
});
App.Person = Ember.Object.extend({
id:null,
fname:"",
lname:"",
gender:null
});
App.Gender = Ember.Object.extend({
id:null,
type:null
});
html/hbs
created a view that takes care of how each App.Person instance gets rendered. As example partial and layouts have been used to accomodate bootstrap styling, as i noticed you used some in your example.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="persons">
{{#each person in this}}
{{view App.PersonFormView}}
{{/each}}
<br/><br/>
{{partial "buttons"}}
</script>
<script type="text/x-handlebars" data-template-name="_buttons">
<button type="button" class="btn btn-primary" {{action "addPerson"}}>
add
</button>
<button type="button" class="btn btn-primary" {{action "print"}}>
print results to console
</button>
</script>
<script type="text/x-handlebars" data-template-name="personForm">
<div class="row">
<div class="col-md-6 col-xs-5">
<div class="form-group">
<label>First Name</label>
{{input class="form-control" placeholder="First Name" value=person.fname}}
</div>
</div>
<div class="col-md-6 col-xs-5">
<div class="form-group">
<label>Last Name</label>
{{input class="form-control" placeholder="Last Name" value=person.lname}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-xs-4">
{{
view Ember.Select
prompt="Gender"
content=controller.genders
optionValuePath="content.id"
optionLabelPath="content.type"
selectionBinding=person.gender
class="form-control"
}}
</div>
</div>
<!--</div>-->
</script>
<script type="text/x-handlebars" data-template-name="simple-row">
<div class="row">
{{yield}}
</div>
<br/><br/>
</script>
<script type="text/x-handlebars" data-template-name="collapsible-row">
<div class="panel-group" >
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href=#{{unbound person.id}}>
person:{{person.fname}}
</a>
</h4>
</div>
<div id={{unbound person.id}} class="panel-collapse collapse">
<div class="panel-body">
{{yield}}
</div>
</div>
</div>
</div>
</br>
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.1.2.js"></script>
<script src="http://builds.emberjs.com/tags/v1.2.0/ember.min.js"></script>
</body>
</html>

Categories

Resources