getAttribute value with AngularJS - javascript

I have the following controller... I'm trying to get the name and rating attibute from an HTML input, but I get the error TypeError: angular.element(...).getAttribute is not a function
app.controller('courseReview', function ($scope, $http) {
$scope.rateThis = function rateThis(el){
var elName = angular.element(el).getAttribute('name');
var rating = angular.element(el).getAttribute('rating');
document.getElementById(elName+'Rating').value = rating;
}
});
HTML
<div ng-controller="courseReview">
<!-- radio input -->
<input class="star-5" id="wstar-5" rating="5" type="radio" name="welcome" ng-click="rateThis(this)"/>
</div>
Is there another way to do this?

As per the documentation "https://docs.angularjs.org/api/ng/function/angular.element", to get attribute of an element you need to use
.attr('name');
in place of
.getAttribute('name');
Important
You are passing this in your html, here this will not pass the DOM element to the function, rather it will refer to the scope. To pass the current element pass $event
HTML Change
ng-click="rateThis(this)" to ng-click="rateThis($event)"
JS Change
$scope.rateThis = function rateThis($event){
var elName = angular.element($event.target).attr('name');
var rating = angular.element($event.target).attr('rating');
document.getElementById(elName+'Rating').value = rating;
}
For reference - http://plnkr.co/edit/ZQlEG33VvE72dOvqwnpy?p=preview

Related

AngularJS - Get values from 'ng-model' and then filter

I have a modal being loaded into a directive and it has a button with a few of attributes.
app.directive('dataFactoryModal', ['$compile', '$timeout', function($compile, $timeout) {
return {
scope: { .... }
link: function (scope, element, attrs) {
var html = '
<input ng-model = "recipients" name = "email" type = "text" placeholder = "Enter email(s)" >\
....
// Modal button section
<button type = "button" class = "btn btn-primary" data-factory = "{{dataFactoryCodes}}" data-recipients = "">Submit</button>\
....
';
....
}
}
}
Now I need to insert all typed emails from the input (with ng-model of 'Recipients') inside the "data-list" attribute of the button.
Something like below:
<button type = "button" class = "btn btn-primary" data-factory = "123;109;129" data-recipients = "meme#email.com;yayaya#email.com">Submit</button>
On the input recipients, you can type multiple email addresses but should be separated only with comma.
Of course, ng-model is there to the rescue. So...
<button type = "button" class = "btn btn-primary" data-factory = "{{dataFactoryCodes}}" data-recipients = "{{recipients}}">Submit</button>
But the tricky part is to replace all commas with semi-colons.
So far I added the ff on the directive. But no success to make it work.
Direct replace filter
scope.replaceCommas = function(value) {
if (value!==undefined) {
return value.replace(',', ';');
}
}
and then call the function inside the attribute like:
data-list = {{replaceCommas(recipients)}}
The results:
data-list = "email#email.com;email2#email.com,email3#email.com"
It's only replacing the first comma and not the succeeding emails being added.
I also tried using $watch, but got not success.
scope.$watch('recipients', function(newValue, oldValue) {
scope.email = newValue;
// if I did this, this would replace all commas with semicolons on the button attribute AND on the textfield
scope.email = newValue.replace(',', ';');
// if I did this, this would just replace only the first comma
scope.emailTags = newValue.replace(',', ';');
}
and then, on the button...
data-list = {{emailTags}}
Why is this not working?
Method 1: split and join:
Having: var list = "email#email.com,email2#email.com,email3#email.com";
Call: list.split(',').join(';')
Method 2: Regex: list.replace(/,/g,';')
The Invocation
I recommend against watchers, and favor creating a submit() function that will perform this operation? Why? Performance. Having to register watchers to see when a value changes is creating additional overhead, and you know when the user is completed because they will click your Submit button. With the watcher method, you will most likely end up running the replacement function more than once.
If you do require the updates as you go, I recommend the use of ng-change, an example of which is outline in this post. Take special note of the debounce function which will limit how frequently this fires.
The submit() function approach:
<button type = "button" class = "btn btn-primary"
data-factory = "{{dataFactoryCodes}}"
data-recipients = "{{recipients}}"
ng-click="submit()"> <!-- Add this -->
Submit
</button>
Then, create a function:
scope.submit = function(value) {
// replace function here
}
Also of interest in this matter may be performance. This link will test the different methods. The Regex version wins here for performance.
https://jsperf.com/split-join-vs-replace/2
use global replace
scope.replaceCommas = function(value) {
if (value!==undefined) {
return value.replace(/,/g,";")
}
}

Angular JS - ng-repeat repeating old values

I am new to Angular JS. I have created a code in angular using app and controller. What I am tyring to do is to add name dynamically to a array when a button is clicked.
By default my array has two value passed. When i give an input and click the add button,it adds the string for the first time.
But when i give another input and click add again, the old string is replaced by the new string and the new string is added again.
Here is the piece of code on JSFiddle: http://jsfiddle.net/5DMjt/3680/
var demo= angular.module("demo",[]);
var simplecontroller = function($scope){
$scope.members = [{id:1,name:'prateek'},{id:2,name:'Ruchi'}];
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push(newmeber);
demo.controller(simplecontroller);
}
}
and here is the HTML Code:
<div ng-app="demo">
<div ng-controller="simplecontroller">
<ul>
<li ng-repeat="member in members">{{member.id}}-{{member.name}}</li>
</ul>
Name<input type="Text" ng-model="inputmember.name">
</br><h2>
{{inputmember}}
</h2>
<input type="button" value="Add" ng-click="addmember(inputmember)">
</div>
</div>
Please Help !
What i analyzed is that push function is passing the address that is why binding still exists.What u can do is pass the value instead like i did below-:
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push({id:newmember.id,name:newmember.name});
demo.controller(simplecontroller);
}
Hope this solves your problem.Happy learning :)
You have two options.
Either you can reinitialize it every time what I would not recommend.
And the other one is to, pass the parameters with values.
$scope.members.push({id:newmember.id,name:newmember.name});
:)
See this updated fiddle: http://jsfiddle.net/5DMjt/3689/
Name<input type="Text" ng-model="newname">
This gives you a scope variable newname.
<input type="button" value="Add" ng-click="addmember()">
And addmember function uses this newname to create a new object and add it to the list:
$scope.addmember = function(){
var newmember = {};
newmember.id = $scope.members.length+1;
newmember.name = $scope.newname;
$scope.members.push(newmember);
}
You have a syntax error. See console error for more info.
Your variable inputmember is not defined anywhere.
Also you need to push to array new reference of the object, so the old one in array does not change each time you type value.
Here is a working version.
http://jsfiddle.net/a9zvgm8k/
$scope.addmember = function(newMember){
newMember.id = $scope.members.length+1;
$scope.members.push(angular.extend({}, newMember));
demo.controller(simplecontroller);
}
$scope.members = $scope.members.concat({id: newmember.id, name: newmember.name});
Solved : http://jsfiddle.net/5DMjt/3693/
Before pushing to $scope.members you need to create a new object and populate it with id and name from the input.

Angularjs - how to bind to an html element appended by javascript code

I want to bind angular event and model to an html element appended by javascript code.
My code is here. https://jsfiddle.net/hq7qk48n/13/
<div ng-app>
<div ng-controller="MyController">
<input type="text" ng-model="text1">
click1
<div id="append"></div>
<p ng-if="clickedTime1">click1 : {{ clickedTime1.toLocaleString() }}</p>
<p ng-if="clickedTime2">click2 : {{ clickedTime2.toLocaleString() }}</p>
<p>{{ text1 }}</p>
<p>{{ text2 }}</p>
</div>
</div>
function MyController($scope) {
$scope.clickedTime1 = null;
$scope.clickedTime2 = null;
$scope.onClick = function () {
var html = '<input type="text" ng-model="text2" name="text"> click2';
$("#append").empty();
$("#append").append(html);
$scope.clickedTime1 = new Date();
}
$scope.onClick2 = function () {
$scope.clickedTime2 = new Date();
};
}
onClick2() doesn't work. and model "text2" is not updated.
How to bind onClick2 function and text2 model?
Need to compile an html element? How?
This is a little tricky because you have an ng-click in your new element. There are 2 things we need to deal with.
Correctly add the element
Make your new element see the scope
First we will start with your call to the method from your element. You will need to add $event to the call
click1
The $event object will give you information about the calling element.
You also need to add it to your method
$scope.onClick=function($event){
Next, your element required use of the scope so we need to turn it into an element. Otherwise just html would be fine.
var el=angular.element('<input type="text" ng-model="text2" name="text"> <a href="#" ng-click="onClick2()"/>click2</a>');
Now you can use a little jquery but exactly on the target element the way angular would do it.
$($event.currentTarget).empty();
$($event.currentTarget).append(el);
At this point you would see your changes but the bindings will not work because it is not attached to the scope so we need to compile it. You will need to add the $compile server to your controller
function MyController($scope,$compile) {
Now we can use the service to compile the new element
$compile(el)($scope);
You should now see everything functioning the way you would expect
function MyController($scope,$compile) {
$scope.clickedTime1 = null;
$scope.clickedTime2 = null;
$scope.onClick = function ($event) {
var el = angular.element('<input type="text" ng-model="text2" name="text"> click2');
$($event.currentTarget).empty();
$($event.currentTarget).append(el);
$compile(el)($scope);
$scope.clickedTime1 = new Date();
}
$scope.onClick2 = function () {
$scope.clickedTime2 = new Date();
};
}
and don't forget to add the $event to your call as well.
I did not use your exact code but I tested this as I answered to verify and it worked perfectly. It might not be best practice to work with the DOM elements in your controller but sometimes it just works. That is how you do it.

edit update existing array in javascript

I am making CRUD app for learning purpose. I need to update existing javascript array on click of edit button. However currently its not updating the existing array rather then its creating new record. Below is the JS code of controller
For Add screen below is the controller code
.controller('addController', ['$scope','$location','$rootScope', function(scope,location,rootScope){
scope.save = function (){
scope.personName = document.getElementById('name').value;
scope.personDesc = document.getElementById('desc').value;
scope.person = {'name' : scope.personName, 'desc' : scope.personDesc};
if(typeof rootScope.crew === 'undefined'){
rootScope.crew = [];
}
rootScope.crew.push(scope.person);
location.path("/");
}
}])
For Edit Screen, below is the code of controller :-
.controller('editController',['$scope','$location','$routeParams','$rootScope', function(scope,location,routeParams,rootScope){
var oldName = scope.crew[routeParams.id].name;
document.getElementById('name').value = scope.crew[routeParams.id].name;
document.getElementById('desc').value = scope.crew[routeParams.id].desc;
scope.editSave = function(){
scope.person = {
'name' : document.getElementById('name').value,
'desc' : document.getElementById('desc').value
}
rootScope.crew.push(scope.person);
location.path("/");
}
}])
Currently I am adding record in existing array rather updating.
Please suggest
The problem is you are pushing a new item to the array. You need to just update the existing person with the person in scope.
.controller('editController',['$scope','$location','$routeParams','$rootScope', function(scope,location,routeParams,rootScope){
var person = scope.crew[routeParams.id]
scope.person = {
name = person.name,
desc = person.desc
};
scope.editSave = function(){
scope.crew[routeParams.id] = scope.person;
location.path("/");
}
}])
In your edit view you would have this:
<input type="text" id="name" ng-model="person.name"/>
<input type="text" id="desc" ng-model="person.desc"/>
It's also worth mentioning that there is no need to have code such as document.getElementById as angular will handle the model binding for you so you don't have to interact with the dom using javascript.
Every object that you are pushing in array must be identified by some id.So assign one id attribute to the person object that you are pushing.
Now come to the edit.html
<tr ng-repeat="p in person">
{{p.name}}
//In button I am passing id which I used in editing the person object
<button ng-click="edit(p.id)"></button>
</tr>
//In controller
edit(id){
//firstly search for the person which is going to be updated
for(i=0;i<arrayInWhichYouArePushingData.length;i++)
{
if(arrayInWhichYouArePushingData[i].id==id)
{
arrayInWhichYouArePushingData[i]=UpdatedData;
break;
}
}
This is just an algorithm to solve this type of problem.You have to modify little bit.

Javascript to get the id of the hyperlink clicked

I would like to know how i can set the current hyperlink id to a hidden field on clicking the corresponding links. The html control code is as follows:
<a href="#TB_inline?height=155&width=300&inlineId=hiddenModalContent" class="thickbox" id="ExpressionsLink"
title="Create expression column" onclick="keepID()">Add Expressions Model</a>
<a href="#TB_inline?height=155&width=300&inlineId=hiddenModalContent" class="thickbox" id="AggregateMethodLink"
title="Create aggregate column">Add Aggregate Methods</a><input id="HiddenIdHolder"
type="hidden" />
I need the id of the link clicked on the hidden field 'HiddenIdHolder'.
Javascript
function keepID() {
var hiddenInput = document.getElementById("HiddenIdHolder");
hiddeninput.value= ? // What can i do here to get the id?
}
this refers to the element itself. Example on jsFiddle
onclick="keepID(this)"
Then
function keepID(element)
{
var hiddenInput = document.getElementById("HiddenIdHolder");
hiddeninput.value = element.getAttribute("id");
}
Use jQuery:
$('a').click(function() {
$('#HiddenIdHolder').val($(this).attr('id'))
})
You should modify your HTML to provide argument for KeepID function:
ooxx
note that you should provide a this argument when invoke KeepID function, then in KeepID function, you can access this element from argument:
function KeepID(src) {
document.getElementById("HiddenIdHolder").value = src.id;
}

Categories