Need help adapting code from jQuery to Angular - javascript

I found some code here: Textarea limit characters for each row in javascript
I want to use it in my project, but I'm having trouble figuring out how to make it work in Angular, particularly setting the directives.
Here's the relevant fiddle: http://jsfiddle.net/aSU7x/
Do I just change
onchange="Validate(this)" onkeyup="Validate(this)"
to
ng-change="Validate(this)" ng-keyup="Validate(this)"
?
I'm still not too familiar with Angular, and I'm only slightly more familiar with jQuery. What would I have to do with the scope, controller, etc.? What would a proper Angular implementation of this code look like? Thanks for the time.

Basic idea of calling a function in angular using scope and $event
angular.module('changeExample', [])
.controller('ExampleController', ['$scope',
function($scope) {
$scope.keyupfnc = function(evt) {
console.log(evt.which);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="changeExample">
<div ng-controller="ExampleController">
<input type="text" ng-keyup="keyupfnc($event)" />
</div>
</div>

Related

Angular JS: data binding with dynamically added html elements

I am facing problems with two way data binding in angular js. Here is the sample code.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body ng-app="">
<div>
<p>Input something in the input box:</p>
<p>Name: <input type="text" ng-model="name"></p>
<div id="jack">
</div>
<script>
$("document").ready(function(){
$("#jack").append("<p ng-bind='name'></p>");
});
</script>
</body>
</html>
Over here I am dynamically adding a paragraph with ng-bind to a div called jack using jQuery
For some reason when I type something in input box it is not reflecting in paragraph with ng-bind property.
I am a novice in angular js and would request you to provide me a simple solution to tackle this issue.
You cannot use jQuery to modify DOM outside Angular this way. Angular does not know about that binding as it was not compiled by Angular.
To solve this particular sample, simply remove the jQuery script and change the HTML to this:
<p>Input something in the input box:</p>
<p>Name: <input type="text" ng-model="name"></p>
<p ng-bind="name"></p>
The example above will work, but I imagine this was not a real-world example. If you post a more specific scenario, I can update my answer to help you solve that.
Edit
Based on your comment, I would create a simple directive to which you could pass your template, it would compile the template and inject the compiled template in the DOM.
Directive:
function myTemplateCompile($compile) {
return {
restrict: 'E',
link: link
}
function link(scope, elem, attrs) {
attrs.$observe('template', (template) => {
elem.html(template);
$compile(elem.contents())(scope);
});
}
}
HTML
<my-template-compile template="any HTML you might need including bindings"></my-template-compile>
You can then change the template attribute of the directive on the fly and it will re-compile and update the DOM based on the new value.
The example above should point you in the right direction. I just have to warn you, that this might be quite dangerous. If the content you are injecting is coming from some user input, this might have very severe security implications. Please make sure you are not exposing your application to attacks.
Well first we need to define the app and create custom directive.
var myApp=angular.module('myApp',[])
.controller('myCtrl',function($scope){
$scope.name="Your name";
})
myApp.directive('myDirective', function() {
return {
restrict: 'E',
template: '<span data-ng-bind="name"></span>'
};
});
After this you need to use above created directive as like below
<my-Directive></my-Directive>

Update input value

I am building a drum machine using AngularJS and having issues adjusting the tempo from the user interface.
I have got the object "this.tempo=120" & "<input class="bpm-input" type="number" onchange="updateBPM()" min="100" max="150" ng-model="$ctrl.tempo"></input>"
This doesn't seem to update the tempo value, only the value shown in the input box.
What function would I need to update the value within the controller?
It is normal, when you use AngularJS, you need to use the Angular WAY.
In other words, what angular do for you is the only way to do it.
AngularJS drastically control your DOM and use it as a copy.
If you change the DOM without the angular behavior, angular cannot update his copy and throws bad behaviors.
You need to use all Angular things, to tell him to apply his magic on your DOM.
Change your onclick attribute by ng-click angular directive, put your updateBPM into your controller scope, and this will works.
Hope that helps you!
Basic things you can do are as in the attached snippet also try having Angular patterns for a manageable code base and good performance Patterns
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myController as myCtrl">
<input class="bpm-input" type="number" ng-change="myCtrl.updateBPM()" min="100" max="150" ng-model="myCtrl.tempo"></input>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
var myCtrl = this;
myCtrl.tempo=120;
myCtrl.updateBPM = function(){
alert(myCtrl.tempo);
}
});
</script>
</body>
</html>
Code is attached below
<script>
var mainModule = angular.module('mainModule', [])
.controller('mainCntrl', function($scope) {
var vm = this;
vm.tempo = 120;
});
</script>
<div ng-app="mainModule">
<div ng-controller="mainCntrl as ctrl">
<input class="bpm-input" type="number" min="100" max="150" ng-model="ctrl.tempo"></input>
</div>
</div>

Dynamically add angular attributes to old html forms

I have a project where I'm currently trying to refactor an old system that was hinged on jquery from the ground up with angular 1.x. However, there are a lot of old HTML forms that I'd like to reuse the bulk of so I don't want to recreate them. I'd love it if there was a way to keep it purely angular, but I'm honestly at a loss of how I'd do that (or whether or not I can). I'm fairly new to angular so there are a lot of inner workings to it that I'm still not privy to.
I've searched around on google and other places including here and I can't really even find other people talking about it. That tells me that either I'm searching badly or it's something that I should probably not be working towards.
All the html pages have identically id'd fields so I feel I can reliably base things on that. For example: all forms with first name text boxes have an id of "cl_fname".
Is there anyway that I can accomplish: getting the form, adding an ng-model="cl_fname" or something to the relevant tag and then display the form? I've gotten to the point where I can get the html page, hold it in the scope and then display using ng-bind-html, but figuring out how to add angular attributes to specific elements I can't figure out.
You can achieve this with jQuery and the attr() method.
I created a plunker here that demonstrates adding angular to an existing "plain" html form.
In the example, I'm using id selectors, but you could use any combination of selectors to ensure you get the right elements.
The below is a quick code snippet from my Plunker example:
HTML:
<div ng-app="myApp">
<form id='myForm1' data-test="test2">
<span>First Name:</span>
<input type="text" id="myForm1_firstName" />
<input type="submit" id="myForm1_Submit" value="Go!" />
</form>
</div>
JS:
// set up angular
var myApp = angular.module('myApp', []);
myApp.controller('MyForm1Controller', ['$scope', function($scope) {
$scope.firstName = 'Angular Working!';
}]);
// use jQuery to add the relevent attributes to our form
var jqMyForm1 = $('form#myForm1');
var jqTxtFirstName = jqMyForm1.find('input[type="text"]#myForm1_firstName');
//add controller to form
jqMyForm1.attr('ng-controller', 'MyForm1Controller');
//bind the textbox to the angular 'firstName' variable
jqTxtFirstName.attr('ng-model', "firstName");
EDIT:
just realised you want to load the html form dynamically.
Version 2 of the plunker (here) will now dynamically load a HTML form from an external resource (separate html page), inject it into the current page, add the angular bindings to it, and then get angular to recognise it.
The key to getting angular to recognise the form is the use of the $compile object (angular $compile documentation).
Again, quick snippets of the code in use:
HTML (main page):
<div ng-app="myApp" ng-controller="LoadingController"></div>
HTML (myForm1.html):
<form id='myForm1' data-test="test2">
<span>First Name:</span>
<input type="text" id="myForm1_firstName" />
<input type="submit" id="myForm1_Submit" value="Go!" />
</form>
JS:
// set up angular
var myApp = angular.module('myApp', []);
// main controller for loading the dynamic form
myApp.controller('LoadingController', ['$scope','$http','$compile', function($scope,$http,$compile) {
$scope.loadHtmlForm = function(formURL) {
$http.get(formURL).then(function successCallback(response){
var jqForm = $(response.data);
var jqTxtFirstName = jqForm.find('input[type="text"]#myForm1_firstName');
//add controller to form
jqForm.attr('ng-controller', 'MyForm1Controller');
//bind the textbox to the angular 'firstName' variable
jqTxtFirstName.attr('ng-model', "firstName");
$('div').append(jqForm);
$compile(jqForm[0])($scope);
});
}
$scope.loadHtmlForm('myForm1.html');
}]);
// form controller for managing the data
myApp.controller('MyForm1Controller', ['$scope', function($scope) {
$scope.firstName = 'Angular Working!';
}]);

How to convert jQuery code into usable AngularJS code

I am new to AngularJS and would like to create functionality for a login page similar to what you find here when you click the 'Forgot Password' link:
http://bootsnipp.com/snippets/featured/login-amp-password-reminder#comments
Is it best to use a directive, since this is behavioral, instead of a controller? I've tried quite a bit with creating a controller for it, but as I search for help on the subject I find that using a controller for this may not be the way to go. Here was my latest trials which was unsuccessful (the link does nothing when clicked):
on controller side in a js file:
angular.module('mean.users')
.controller('SwitcherCtrl', ['$document',
function($document) {
$document.ready(function () {
$document.getElementById('olvidado').click(function (e) {
e.preventDefault();
$document.getElementById('form-olvidado').toggle('500');
});
$document.getElementById('acceso').click(function (e) {
e.preventDefault();
$document.getElementById('form-olvidado').toggle('500');
});
});
}
])
on html side, I included ng-controller="SwitcherCtrl" where necessary.
JQuery approach is completely incompatible with AngularJS. DOM Manipulation is only allowed in directives in the link function otherwise it is a very bad practice. Try to start from scratch and forget about JQuery. The magic of AngularJS happens with 2-way bindings.
You could use a directive, with a login controller and a factory/service to hold the username and password and send it to the database. For this login there is definitely no need for JQuery at all. You can check this question here:
AngularJS- Login and Authentication in each route and controller
edit: In your question above, it is not a directive instead of a controller. A directive can have a controller that is applied to a specific scope. You could do the same thing with both but depends how many times you will reuse this login snippet - I guess you won't need it but I believe it is still good practice to make one.
edit 2: if you havent' read this one, please do it! I believe you will answer most of your questions about the two different (opposite I would say) technologies. "Thinking in AngularJS" if I have a jQuery background?
Also since I came from Jquery background too, I followed these four resources in order and now I can make most of the things I want:
Introduction to Angular.js in 50 Examples (part 1) https://www.youtube.com/watch?v=TRrL5j3MIvo
Introduction to Angular.js in 50 Examples (part 2) https://www.youtube.com/watch?v=6J08m1H2BME
Free Interactive AngularJS learning for Beginners https://www.codeschool.com/courses/shaping-up-with-angular-js
More AngularJS resources by topic egghead.io https://egghead.io/technologies/angularjs
edit 3: Since I saw good interest in my answer I decided to expand it with what to avoid/best practices so the code is more testable, maintainable and easier to migrate to Angular 2:
5 Guidelines For Avoiding Scope Soup in Angular
http://www.technofattie.com/2014/03/21/five-guidelines-for-avoiding-scope-soup-in-angular.html
No $scope soup, bindToController in AngularJS
https://toddmotto.com/no-scope-soup-bind-to-controller-angularjs/
Angular JS - you probably shouldn't use $watch in your controllers.
http://www.benlesh.com/2013/10/title.html
11 Tips to Improve AngularJS Performance
http://www.alexkras.com/11-tips-to-improve-angularjs-performance/
You can try this out, it uses directives and html. Whether the login or forgot username shows is tied to the state of a scope variable in the directives link function.
Fiddle
<div ng-app="myApp">
<div my-auth>
<div ng-show="active">
<form name="login">
<input type="email" ng-model="email" placeholder="your#email.com" required />
<input type="password" ng-model="passwd" required />
<button ng-disabled="!login.$valid">Login</button>
</form>
forgot password?
</div>
<div ng-show="!active">
<form name="forgot">
<input type="email" ng-model="email" placeholder="your#email.com" required />
<button ng-disabled="!forgot.$valid">Reset Password</button>
</form>
access
</div>
</div>
</div>
The directive
angular.module('myApp', [])
.directive('myAuth', function(){
return {
link: function(scope, elem, attr){
scope.active = true;
scope.toggle = function(){
scope.active = !scope.active;
};
}
};
});
Thanks to everyone who answered. They kicked off this thing moving in the right direction and I was able to improve upon it to come to the exact answer shown below.
The HTML:
<div ng-controller="SwitcherCtrl">
<div data-fold-toggle="active">
<form id="login">
<input type="email" ng-model="email" required="">
<input type="password" ng-model="password" required="">
<button type="submit">Login</button>
<a ng-click="active=!active">Forgot your password?</a>
</form>
</div>
<div data-fold-toggle="active" style="display: none;">
<form id="forgotpw">
<input type="email" ng-model="email" required="">
<button type="submit">Reset Password</button>
<a ng-click="active=!active">Account Access</a>
</form>
</div>
</div>
The Controller & Directive:
.controller('SwitcherCtrl', function($scope) {
$scope.active = true;
})
.directive('foldToggle', function() {
return {
restrict: 'A',
scope:{
isOpen: '=foldToggle'
},
link: function(scope, element) {
scope.$watch('isOpen', function(newVal,oldVal){
if(newVal !== oldVal){
element.toggle(200);
}
});
}
};
});

Angular JS and ng-model not displaying

I am a newbie at Angular JS and this is what I started with:
var myApp = angular.module('myApp', []);
myApp.controller('WizardController', ['$scope', function($scope){
$scope.user = {};
$scope.displayName = 'Hello';
}]);
user is used to gather the data in the input fields in my steps <input type='text' ng-model='user.name'> and when I call it like so {{user.name}} what is inside the input text appears in a next step.
My question is how do I get $scope.displayName to display on my page.
<p ng-model="displayName"></p>
<p>{{displayName}}</p>
<p><input type='text' ng-model='displayName'></p>
I have tried all of these and none seem to work. Please help.
here is a jfiddle http://jsfiddle.net/Fc7KZ/
Make sure you added the ng-app and ng-controller attributes to your html
<body ng-app="myApp" ng-controller="WizardController">
<p ng-model="displayName"></p>
<p>{{displayName}}</p>
<p><input type='text' ng-model='displayName'></p>
</body>
Update 1:
Your js fiddle did not have angular library here is the version corrected:
http://jsfiddle.net/Fc7KZ/2/
You seem to be using angular-wizard. Your Fiddle doesn't include Angular or Lodash, which are both pre-requisites of that project. I'm guess your local code doesn't either, if not then that's your problem.

Categories

Resources