Unable to Set Angular Model from Javascript - angularjs

I tried to set an angularjs model value from a Javascript code but it doesn't work. I always get an empty value for that property. Below is a snippet of my html code:
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformScripts: true,
usePlatformStyles: true
});
VSS.ready(function () {
console.log("Organization name " + VSS.getWebContext().account.name);
var scope = angular.element(document.querySelector('#hubContainer')).scope();
scope.$apply(function () {
scope.DashboardModel.AccountKey = VSS.getWebContext().account.name;
})
});
</script>
<div class="ng-cloak tree-master-wrapper">
<div id="hubContainer" class="ng-scope" data-ng-controller="MyController">
Some code comes here…….
</div>
But for some reasons the console.log(“AccountKey “ + $scope.DashboardModel.AccountKey) is empty. Any idea? I using https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js

I was able to resolve this by adding this entry to "MyController":
MyModule.controller('MyController', ['$scope', function($scope){
$scope.DashboardModel = new DashboardModel();
var checkPermission = function (selectedTeam) {
VSS.require(["VSS/Service", "VSS/Security/RestClient"],
function(VSS_Service, Security_RestClient) {
$scope.DashboardModel.AccountKey = VSS.getWebContext().account.name;
});
});
}

Related

Passing data via service not updating second controller

I am trying to use service in AngularJS and pass data from one controller to another on click of a button.
I tried and can see that service value is updated but I am unable to retrieve in the second controller, however, I can retrieve in the first Controller.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<p>Search:<input type="text" ng-model="newValue"></p>
<button ng-click="myFunc(newValue)">OK</button>
</div>
<div ng-controller="myCtrl2">
{{receivedVal}}
</div>
<script>
var app= angular.module('myApp', []);
app.controller('myCtrl', function($scope,sharedProperties) {
$scope.stringValue = sharedProperties.getString();
$scope.myFunc = function(newValue) {
sharedProperties.setString(newValue);
$scope.stringValue = sharedProperties.getString();
console.log($scope.stringValue);
//I am getting the value here by calling sharedProperties.getString();
};
});
app.controller('myCtrl2', function($scope,sharedProperties) {
$scope.receivedVal = sharedProperties.getString();
console.log($scope.receivedVal);
//But I am not getting the updated value here by calling sharedProperties.getString();
});
app.service('sharedProperties', function() {
var stringValue = 'firstoccurence';
return {
getString: function() {
return stringValue;
},
setString: function(value) {
stringValue = value;
},
}
});
</script>
</body>
</html>
receivedVal is always coming blank even service is getting updated.
By looking at your HTML code; I can see both the controllers have already been instantiated.
So when you do $scope.receivedVal = sharedProperties.getString(); in controller 2, you are just getting value from service one time only (Note : You are not continuously observing the value from service). And hence in template of controller 2 the default value firstoccurence shall be displayed.
You are actually updating the value on click of OK button, which in turns updates value in service. But there is no way you told angular that now as values has been changed then now controller 2 should get this new value.
To active the scenario that you want , you need to use $broadcast and $on so that you can continuously observe change happening in controller 1.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<p>Search:<input type="text" ng-model="newValue"></p>
<button ng-click="myFunc(newValue)">OK</button>
</div>
<div ng-controller="myCtrl2">
{{receivedVal}}
<button ng-click="thisWillGetValFromService()" >update this scope's value</button>
</div>
<script>
var app= angular.module('myApp', []);
app.controller('myCtrl', function($rootScope,$scope,sharedProperties) {
$scope.stringValue = sharedProperties.getString();
$scope.myFunc = function(newValue) {
sharedProperties.setString(newValue);
$scope.stringValue = sharedProperties.getString();
console.log($scope.stringValue);
//I am getting the value here by calling sharedProperties.getString();
$rootScope.$broadcast('greeting', newValue);
};
});
app.controller('myCtrl2', function($scope,sharedProperties) {
$scope.receivedVal = sharedProperties.getString();
console.log($scope.receivedVal);
//But I am not getting the updated value here by calling sharedProperties.getString();
$scope.$on('greeting', function(ev,val){
$scope.receivedVal = val
})
});
app.service('sharedProperties', function() {
var stringValue = 'firstoccurence';
return {
getString: function() {
return stringValue;
},
setString: function(value) {
stringValue = value;
},
}
});
</script>
</body>
Above snippet shall solve your problem.
Updated :
Consider a scenario where you have routing configuration defined. So by default only controller 1 and its templates loads in HTML. Then you update ur input box and click OK button. This will save data to service.
Then later on consider on click of some link you re redirecting the app to route of your controller 2 so at this point your controller 2 will get instantiated and $scope.receivedVal = sharedProperties.getString(); this will give you updated value.
Its just a matter of when you load your template (controller) In your case you load both the controllers at a time so you need to use broadcast and on. But if your second component going to load sometime later then you can always use service.
Value is updating in the second controller
But it is not reflecting in the :
<div ng-controller="myCtrl2">
{{receivedVal}}
</div>
Because ng-controller creates new scope
you should write one extra method like in this:
https://codepen.io/amar9312/pen/yRJKGj

$sce.trustAsHtml filter is not getting applied with ng-bind-html on dynamic data

I'm trying to display the html content which I receive in my div.testData by using ng-bind-html together with filter.
I've already included 'ngSanitize' in my app.
But somehow, it works only partially. Seem like, filter is not getting applied.
It works fine when I create a local file and check, but doesn't work when I use the same code in my project environment.
Sample data:
$scope.userProfile.Information = '<p>Hello, this is sample data to test html.</p>';
The output displayed is:
'<p>Hello, this is sample data to test html.</p>'
Desired output is :
'Hello, this is sample data to test html.'
Please help me fix this.
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<div class="testData" ng-bind-html= "userProfile.Information | to_trusted"></div>
Filter:
app.filter('to_trusted', ['$sce', function($sce){
return function(text) {
var doc = new DOMParser().parseFromString(text, "text/html");
var rval= doc.documentElement.textContent;
//console.log(rval);
return $sce.trustAsHtml(rval);
};
}]);
You can try like the below code as you have your given working example with this plunker. Please check that too..
Controller:
app.filter('to_trusted', ['$sce', function($sce){
return function(text) {
var txt = document.createElement("textarea");
txt.innerHTML = text;
return $sce.trustAsHtml(txt.value);
};
}]);
Answer is here already.
app.filter('to_trusted', ['$sce', function($sce){
return $sce.trustAsHtml;
}]);
var app = angular.module("Profile",[])
app.directive('toTrusted',function(){
return function(scope,element,attr){
var result = attr.data
var input_val = result.replace(/</g, "<").replace(/>/g, ">").replace(/
/g, "\n");
element[0].innerHTML = input_val;
scope.use_recusrive(element[0].firstElementChild,element[0])
}
})
app.controller("ProfileCtrl", function($scope, $rootScope,$sce){
$scope.valid_input = '<div> div 1 sample <p> div1 indide p tag .</p></div><p> p tag 2.</p> <div>DIV 2 Sample </div>';
$scope.use_recusrive = function(dom,p_node){
if(!dom)
return;
var s_dom = dom.firstElementChild
if(!s_dom){
var text_content = dom.textContent||'';
var tag_name = dom.tagName
var new_text_content = text_content+' to be renedered as '+"'"+tag_name+"'"+' tag.';
dom.textContent = new_text_content;
/*if(s_dom.nextElementSibling)
$scope.use_recusrive(s_dom.nextElementSibling,dom)*/
}else{
$scope.use_recusrive(dom.firstElementChild,dom)
}
var nex_sibling = dom.nextElementSibling
if(nex_sibling){
$scope.use_recusrive(nex_sibling,dom)
}
}
})
div{
color:black;
font-weight:700;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="Profile" ng-controller="ProfileCtrl">
<div to-trusted data={{valid_input}} ></div>
</body>

use createHash in angular-md5

When I wanna use the createHash function in angular, this error raises : md5.createHash is not a function
Here's my code :
MyCtrl.$inject = ['md5'];
function MyCtrl(md5) {
var vm = this;
vm.reg = reg;
function reg() {
vm.avatar = md5.createHash('salam'); // This Line Has Error
console.log(vm.avatar);
...
Note: I added the module dependency fine !
You need to add angular-md5 to your project module as well le below.
angular.module('YOUR_APP', [
'angular-md5', // you may also use 'ngMd5' or 'gdi2290.md5'
'controllers'
]);
Not sure what happened, but you might be able to backtrack from a fiddle I made you
<body ng-app="YOUR_APP" ng-controller="MainCtrl">
<img src="http://www.gravatar.com/avatar/{{ email | gravatar }}.jpg?d=identicon">
<input type="text" ng-model="email" placeholder="Message Here"> {{ message }}
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-md5/0.1.10/angular-md5.js"></script>
<script>
var app = angular.module('YOUR_APP', [
'angular-md5', // you may also use 'ngMd5' or 'gdi2290.md5'
]).controller('MainCtrl', function($scope, md5) {
$scope.$watch('email', function(val) {
$scope.message = 'Your message Hash is: ' + md5.createHash($scope.email || '');
});
});
</script>
`

update angularjs model from jquery [duplicate]

I have this simple scenario:
Input element which value is changed by jQuery's val() method.
I am trying to update the angular model with the value that jQuery set. I tried to write a simple directive, but it's not doing what I want.
Here's the directive:
var myApp = angular.module('myApp', []);
myApp.directive('testChange', function() {
return function(scope, element, attrs) {
element.bind('change', function() {
console.log('value changed');
})
}
})
this is the jQuery part:
$(function(){
$('button').click(function(){
$('input').val('xxx');
})
})
and html:
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input test-change ng-model="foo" />
<span>{{foo}}</span>
</div>
</div>
<button>clickme</button>
Here is the fiddle with my try:
http://jsfiddle.net/U3pVM/743/
Can someone please point me in the right direction?
ngModel listens for "input" event, so to "fix" your code you'd need to trigger that event after setting the value:
$('button').click(function(){
var input = $('input');
input.val('xxx');
input.trigger('input'); // Use for Chrome/Firefox/Edge
input.trigger('change'); // Use for Chrome/Firefox/Edge + IE11
});
For the explanation of this particular behaviour check out this answer that I gave a while ago: "How does AngularJS internally catch events like 'onclick', 'onchange'?"
But unfortunately, this is not the only problem you have. As pointed out with other post comments, your jQuery-centric approach is plain wrong. For more info take a look at this post: How do I “think in AngularJS” if I have a jQuery background?).
Hope this is useful for someone.
I was unable to get the jQuery('#myInputElement').trigger('input') event to be picked up my angular app.
I was however, able to get angular.element(jQuery('#myInputElement')).triggerHandler('input') to be picked up.
The accepted answer which was triggering input event with jQuery didn't work for me. Creating an event and dispatching with native JavaScript did the trick.
$("input")[0].dispatchEvent(new Event("input", { bubbles: true }));
I don't think jQuery is required here.
You can use $watch and ng-click instead
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input test-change ng-model="foo" />
<span>{{foo}}</span>
<button ng-click=" foo= 'xxx' ">click me</button>
<!-- this changes foo value, you can also call a function from your controller -->
</div>
</div>
In your controller :
$scope.$watch('foo', function(newValue, oldValue) {
console.log(newValue);
console.log(oldValue);
});
You have to use the following code in order to update the scope of the specific input model as follows
$('button').on('click', function(){
var newVal = $(this).data('val');
$('select').val(newVal).change();
var scope = angular.element($("select")).scope();
scope.$apply(function(){
scope.selectValue = newVal;
});
});
I made modifications on only controller initialization by adding listener on action button:
$(document).on('click', '#action-button', function () {
$timeout(function () {
angular.element($('#input')).triggerHandler('input');
});
});
Other solutions did not work in my case.
I know it's a bit late to answer here but maybe I may save some once's day.
I have been dealing with the same problem. A model will not populate once you update the value of input from jQuery. I tried using trigger events but no result.
Here is what I did that may save your day.
Declare a variable within your script tag in HTML.
Like:
<script>
var inputValue="";
// update that variable using your jQuery function with appropriate value, you want...
</script>
Once you did that by using below service of angular.
$window
Now below getData function called from the same controller scope will give you the value you want.
var myApp = angular.module('myApp', []);
app.controller('imageManagerCtrl',['$scope','$window',function($scope,$window) {
$scope.getData = function () {
console.log("Window value " + $window.inputValue);
}}]);
I've written this little plugin for jQuery which will make all calls to .val(value) update the angular element if present:
(function($, ng) {
'use strict';
var $val = $.fn.val; // save original jQuery function
// override jQuery function
$.fn.val = function (value) {
// if getter, just return original
if (!arguments.length) {
return $val.call(this);
}
// get result of original function
var result = $val.call(this, value);
// trigger angular input (this[0] is the DOM object)
ng.element(this[0]).triggerHandler('input');
// return the original result
return result;
}
})(window.jQuery, window.angular);
Just pop this script in after jQuery and angular.js and val(value) updates should now play nice.
Minified version:
!function(n,t){"use strict";var r=n.fn.val;n.fn.val=function(n){if(!arguments.length)return r.call(this);var e=r.call(this,n);return t.element(this[0]).triggerHandler("input"),e}}(window.jQuery,window.angular);
Example:
// the function
(function($, ng) {
'use strict';
var $val = $.fn.val;
$.fn.val = function (value) {
if (!arguments.length) {
return $val.call(this);
}
var result = $val.call(this, value);
ng.element(this[0]).triggerHandler('input');
return result;
}
})(window.jQuery, window.angular);
(function(ng){
ng.module('example', [])
.controller('ExampleController', function($scope) {
$scope.output = "output";
$scope.change = function() {
$scope.output = "" + $scope.input;
}
});
})(window.angular);
(function($){
$(function() {
var button = $('#button');
if (button.length)
console.log('hello, button');
button.click(function() {
var input = $('#input');
var value = parseInt(input.val());
value = isNaN(value) ? 0 : value;
input.val(value + 1);
});
});
})(window.jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="example" ng-controller="ExampleController">
<input type="number" id="input" ng-model="input" ng-change="change()" />
<span>{{output}}</span>
<button id="button">+</button>
</div>
If you are using IE, you have to use: input.trigger("change");
add .change() after setting the value.
example:('id').val.('value').change();
also don't forget to add onchange or ng-change tag in html
I did this to be able to update the value of ngModel from the outside with Vanilla/jQuery:
function getScope(fieldElement) {
var $scope = angular.element(fieldElement).scope();
var nameScope;
var name = fieldElement.getAttribute('name');
if($scope) {
if($scope.form) {
nameScope = $scope.form[name];
} else if($scope[name]) {
nameScope = $scope[name];
}
}
return nameScope;
}
function setScopeValue(fieldElement, newValue) {
var $scope = getScope(fieldElement);
if($scope) {
$scope.$setViewValue(newValue);
$scope.$validate();
$scope.$render();
}
}
setScopeValue(document.getElementById("fieldId"), "new value");
Not what OP asked, but for any soul that might be as well writing an userscript that goes through input fields and fills the required details. Nothing (fully) worked for me, but finally managed to get it done this way:
var el = $('#sp_formfield_fw_ip');
el.val("some value");
angular.element(el).triggerHandler('focus');
angular.element(el).triggerHandler('input');
angular.element(el).triggerHandler('change');
angular.element(el).triggerHandler('blur');
Open developer tools, and inspect input field for added events. There I found all of them (in my case): focus, input, change and blur.

How to get the value from ACE-Angular editor

I am having problems on getting Ace code editor results from whatever I type on the code editor.
As you can see I set up my controller with all the functionalities
and options. The only thing that is not working is rendering the results from editor. Thank you in advance....
app.controller('AceCtrl', function ($scope) {
$scope.modes = ['CoffeeScript'];
$scope.mode = $scope.modes[0];
$scope.aceOption = {
mode: $scope.mode.toLowerCase(),
onLoad: function (editor) {
// defaults
editor.setTheme("ace/theme/monokai");
// options
editor.setOptions({
showGutter: true,
showPrintMargin: false,
});
$scope.modeChanged = function () {
editor.getSession().setMode("ace/mode/" + $scope.mode.toLowerCase());
};
}
};
//Runs every time the value of the editor is changed
$scope.aceChanged = function(_editor){
console.log('Ace editor changed');
// Get Current Value
var currentValue = _editor.getSession().getValue();
// Set value
_editor.getSession().setValue('This text is now in the editor');
};
});
<div class="wrapper" ng-controller="AceCtrl">
<section >
<select ng-model="mode" ng-options="m for m in modes" ng-change="modeChanged()" autofocus="0"></select>
<div ui-ace="aceOption" ng-model="aceModel" class="ace_editor"></div>
</section>
<div ng-change="aceChanged" style="border:1px solid red; position:relative; width:50%; height:300px; float:right;"></div>
</div>
If you want to do this in the onChange handler of ui-ace you could get the document from the editor's session and grab it's value:
editor.getSession().getDocument().getValue();
Reference: http://ajaxorg.github.io/ace/#nav=api&api=document
Example code:
<div ui-ace="{
onLoad: aceLoaded,
onChange: aceChanged
}"></div>
<textarea id="ace_document">
{{aceDocumentValue}}
</textarea>
$scope.aceLoaded = function(_editor) {
$scope.aceSession = _editor.getSession();
};
$scope.aceChanged = function () {
$scope.aceDocumentValue = $scope.aceSession.getDocument().getValue();
};
Working example on Plunker: http://plnkr.co/edit/9swlVY9JnIfOnbOAfXui?p=preview
But the easiest way is to assign the value to scope and use ng-model on the directive's element:
Controller:
angular.module('app').controller('rootController', [
'$scope',
function ($scope) {
$scope.aceValue = 'Foobar';
}
]);
Template:
<div ui-ace ng-model="aceValue"></div>
<textarea id="ace_document" ng-model="aceValue"></textarea>
Working example on Plunker: http://plnkr.co/edit/fbtzYDEqIQEwB6Ascm3s?p=preview

Resources