Angular ng-model in appended Html code not working - javascript

This is my code. Where I dynamically add html on a button click.but the ng-model which I gave there is not working.
Can anyone solve my issue
$scope.addParam = function(selected) {
if (selected == "bucket_policy_privacy_status") {
var myElement = angular.element(document.querySelector('#inputParameters'));
myElement.append('<input type="text" style="width:220px" class="form-control" name="" disabled="" value=' + selected + '> <select class="form-control" style="width:196px" ng-model="fields.privacyStatus" ><option value="range">Range</option><option value="public">Public</option><option value="private">Private</option></select> <br><br>');
$scope.$watch('fields.privacyStatus', function() {
var privacy_status = $scope.fields.privacyStatus;
alert();
var status = {
"term": {}
}
status.term[selected] = privacy_status;
output.push(status);
});
$('#params option[value="bucket_policy_privacy_status"]').remove();
$scope.input.select = "bucket_owner";
}
};

There are a few things you will need to change:
You need to use Angulars $compile option to evaluate angular attributes/expressions when inserting HTML dynamically.
Adding the line below after you added the element ot the DOM should do the trick:
$compile(angular.element('.form-control'))($scope);
It basically just let's angular know there is something new it should evaluate and start watching.
(Don't forget to add $compile to your module dependencies).
Further to that I assume you have actually added an object called fields on your $scope?
Another thing you could do is use ng-change on your form instead of using $watch. The function you bind on ng-change would be invoked every time one of the selects in your form changes.
For further reading have a look at this:
https://docs.angularjs.org/api/ng/service/$compile

I think that will not work, you are adding only dom, that's all, there's no bind.
One way is to create directive which will do that, or add that input in template with "ng-hidden", and on click just show.

Related

Adding an element with directives in Angular

I am adding an element dynamically in Angular. The code is as follows.
myelement.after('<input ng-model="phone" id="phone">');
The element gets added and all works fine. However I think I'm missing a step and Angular does not recognize the new element because when I collect data later, the value of the dynamically added element is not defined.
The reason for adding the element on fly is that the number of inputs is not known from the beginning and user can add as many of them as they want. The actual code is like:
myelement.after('<input ng-model="phone"' + counter + ' id="phone' + counter + '">');
I'm sorry, I should have provided complete sample from the beginning. Please see the following jsfiddle, add some phones (with values) and list them: http://jsfiddle.net/kn47mLn6/4/
And please note that I'm not creating any new directive. I'm only using Angular standard directives, and I prefer not to create a custom directive for this work (unless required).
Assuming that you are adding element to the DOM using directive. You can use built in angular service $compile.
Firstly inject the $compile service to your directive. Then in your link function of the directive, get your myElement after which you want to append your element. Then create your element using angular.element(). Then compile it using $compile service and pass the scope in which you are in now.(Here this scope is the directive scope). After getting the compiled dom element you can just append it after your myElement.
here is an example about how you can add element dynamically from directive:
var elementToBeAdded = angular.element('<input ng-model="phone" id="phone">');
elementToBeAddedCompiled = $compile(elementToBeAdded)(scope);
myElement.append(elementToBeAddedCompiled);
If you add your element using $compile service in your directive, angular will recognize your dynamically added element.
I was trying to accomplish this without using directives, but it seems the best way (and probably the only proper way) of adding multiple elements to DOM in Angular is by defining a custom directive.
I found a very nice example here http://jsfiddle.net/ftfish/KyEr3/
HTML
<section ng-app="myApp" ng-controller="MainCtrl">
<addphone></addphone>
<div id="space-for-phones"></section>
</section>
JavaScript
var myApp = angular.module('myApp', []);
function MainCtrl($scope) {
$scope.count = 0;
}
//Directive that returns an element which adds buttons on click which show an alert on click
myApp.directive("addbuttonsbutton", function(){
return {
restrict: "E",
template: "<button addbuttons>Click to add buttons</button>"
}
});
//Directive for adding buttons on click that show an alert on click
myApp.directive("addbuttons", function($compile){
return function(scope, element, attrs){
element.bind("click", function(){
scope.count++;
angular.element(document.getElementById('space-for-buttons')).append($compile("<div><button class='btn btn-default' data-alert="+scope.count+">Show alert #"+scope.count+"</button></div>")(scope));
});
};
});
//Directive for showing an alert on click
myApp.directive("alert", function(){
return function(scope, element, attrs){
element.bind("click", function(){
console.log(attrs);
alert("This is alert #"+attrs.alert);
});
};
});
in the angular mind you should manipulate the dom from the JS code.
and use ng-* directive
So i don't know you code but i think you just need to do something like :
View
<button ng-click="showAction()">Show the phone input</button>
<input ng-show="showPhone" ng-model="phone" id="phone">
Controller
app.controller('ctrl', [function(){
$scope.showPhone = false;
$scope.showAction = function() {
$scope.showPhone = true;
};
}]);
Outside of Angular you would need to use the event handler to recognize new elements that are added dynamically. I don't see enough of your code to test, but here is an article that talks about this with $.on():
Jquery event handler not working on dynamic content
Here is a good article that will help with directives and may solve your problem by creating your own directive:
http://ruoyusun.com/2013/05/25/things-i-wish-i-were-told-about-angular-js.html#when-you-manipulate-dom-in-controller-write-directives

How to know add element to an array if checkbox is checked and remove it if unchecked?

Here is my code on HTML. I find it on google that I can use this.
<input type="checkbox" ng-true-value="addTitle(cpPortfolioItem)" ng-false-value="removeTitle(cpPortfolioItem)">
Here is my angularJS controller.
$scope.addTitle = function(cpPortfolioItem){
$scope.selectedTitles.push(cpPortfolioItem.id);
console.log('$scope.selectedTitles', $scope.selectedTitles);
};
$scope.removeTitle = function(cpPortfolioItem){
$scope.selectedTitles.splice(cpPortfolioItem.id,1);
console.log('$scope.selectedTitles', $scope.selectedTitles);
};
it doesn't work. I have logged it in console but I can see it neither push or splice the array. Maybe ng-true-value is not a valid directive? Anyone can help me on this? I will really appreciate it.
Base on the documentation ng-true-value and ng-false-value value are not event handlers. These are the value set to the model when input is checked(ng-true-value) or unchecked(ng-false-value).
Use this instead or use ng-model and attach $watch to the model.
Use ng-change
<input type="checkbox" ng-change="titleChange()" ng-model="titleChanged">
In controller,
$scope.titleChanged = false;
$scope.titleChange = function() {
if ($scope.titleChanged) {
$scope.addTitle(cpPortfolioItem);
} else {
$scope.removeTitle(cpPortfolioItem);
}
}
Working example:-
http://jsfiddle.net/Shital_D/Lcumc3t7/10/

get the text of div using angularjs

i want to get the text of div using angularjs . I have this code
<div ng-click="update()" id="myform.value">Here </div>
where as my controller is something like this
var myapp= angular.module("myapp",[]);
myapp.controller("HelloController",function($scope,$http){
$scope.myform ={};
function update()
{
// If i have a textbox i can get its value from below alert
alert($scope.myform.value);
}
});
Can anyone also recommand me any good link for angularjs . I dont find angularjs reference as a learning source .
You should send the click event in the function, your html code should be :
<div ng-click="update($event)" id="myform.value">Here </div>
And your update function should have the event parameter which you'll get the div element from and then get the text from the element like this :
function update(event)
{
alert(event.target.innerHTML);
}
i just thought i put together a proper answer for everybody looking into this question later.
Whenever you do have the desire to change dom elements in angular you need to make a step back and think once more what exactly you want to achieve. Chances are you are doing something wring (unless you are in a link function there you should handle exactly that).
So where is the value comming, it should not come from the dom itself, it should be within your controller and brought into the dom with a ng-bind or {{ }} expression like:
<div>{{ likeText }}</div>
In the controller now you can change the text as needed by doing:
$scope.likeText = 'Like';
$scope.update = function() {
$scope.likeText = 'dislike';
}
For angular tutorials there is a good resource here -> http://angular.codeschool.com/
Redefine your function as
$scope.update = function() {
alert($scope.myform.value);
}
A better way to do it would be to use ng-model
https://docs.angularjs.org/api/ng/directive/ngModel
Check the example, these docs can be a bit wordy

Accessing yet-to-be-compiled directive's DOM elements from controller

I've got a controller that executes before Angular compiles a directive. The controller needs to manipulate a DOM element that only exists after the directive has been compiled. How can I select that DOM element, to manipulate it, if it's not in the DOM yet?
A contrived example to illustrate this follows. Let's say I have the following markup:
<div ng-controller="CustomerCtrl">
<div customer-list></div>
</div>
customerList is a directive that is transformed into:
<select class="customer-list">
<option value="JohnDoe">John Doe</option>
<option value="JaneDoe">Jane Doe</option>
</select>
CustomerCtrl looks like:
.controller('CustomerCtrl', function() {
var customerList = angular.element('[customer-list]'),
firstCustomer = customerList.children('option:first');
// firstCustomer is length === 0 at this point, so
// this code does not work
firstCustomer.prop('selected', 'selected');
});
My solution was to do this:
.controller('CustomerCtrl', function($timeout) {
var customerList = angular.element('[customer-list]');
// this works
$timeout(function() {
customerList.children('option:first').prop('selected', 'selected');
});
});
What I'm wondering is, is this the appropriate way to do this--using a $timeout()? Is there a best practice about this?
You should be using the directive's link function to do this sort of manipulation. Then you won't have ot use timeout. Such DOM manipulation really belongs to the directive rather than the controller. The controller is simply the holder of scope and really shouldn't have much much of application/ui logic in it.
The link is guaranteed to be called after your directive is compiled so you should be good if you use link.

Add items to drop-down box

I can't seem to find the correct syntax to get this working:
$.get('/templates/mytemplate.html', function (template) {
$(template).find('select').append($("<option />").val(0).text('Please select ...'));
$.each(dashboard.myArray, function () {
$(template).find('select').append($("<option />").val(this.Id).text(this.Text));
});
$('#new-items').append(template);
});
The template variable is just a string of html like:
"<form class="user-item">
<select class=".sc" name="context" />
<input type="hidden" name="id"/>
<input type="hidden" name="date"/>
<form>"
I've tried selecting the select item on name 'select[name=context]' and using a class selector like '.sc' as well ... none seem to work but I've got similar code working fine elsewhere. Very confused.
The problem is template is a string. in your case you are creating a new jQuery wrapper for that element every time and manipulating it but that does not actually change the contents of the string in template, it just changes another in memory object
You need to create a reference to a new jQuery wrapper for template then do the dom manipulation using that reference and at the end append it to the container element
$.get('/templates/mytemplate.html', function (template) {
var $template = $(template);
$template.find('select').append($("<option />").val(0).text('Please select ...'));
$.each(dashboard.myArray, function () {
$template.find('select').append($("<option />").val(this.Id).text(this.Text));
});
$('#new-items').append($template);
});
Demo: Problem, Solution
such code will work
var value = 'some_value',
text = 'some_text';
$('#id').append($('<option value='+value+'>'+text+'</option>'));
the reason your code it's not working is you are modifying a variable but don't assign the changes to variable
$(template).find('select').append($("<option />").val(0).text('Please select ...'));
this line never stores changes to template, it should be :
template = $(template).find('select').append($("<option />").val(0).text('Please select ...'));

Categories