Process input values on ng-click when they changed outside of Angular - javascript

How to pass input values on ng-click when they changed outside of angular. When I type texts myself all works good but once input got dynamic values, ng-click passes empty form. Here the HTML I'll be using:
<form id="form" action="" style="margin:0;">
<img src="jCrop/images/imagename.jpg" id="imgcrop"/>
<input type="text" name="hdnx" id="hdnx" data-ng-model="thumbnail.hdnx" ng-change="alert('test')" />
<input type="text" name="hdny" id="hdny" data-ng-model="thumbnail.hdny" />
<input type="text" name="hdnw" id="hdnw" data-ng-model="thumbnail.hdnw" />
<input type="text" name="hdnh" id="hdnh" data-ng-model="thumbnail.hdnh" />
<button ng-click="save()">Crop Image & Save Selection</button>
</form>
Here is the AngularJS codes:
angular.module('blogAdmin').controller('ThumbnailsController', ["$rootScope", "$scope", "$location", "$http", "$filter", "dataService", function ($rootScope, $scope, $location, $http, $filter, dataService) {
$scope.thumbnail = {};
$scope.save = function () {
if ($scope.thumbnail) {
console.log($scope.thumbnail); //empty log when values changes outside of angular
}
}
}]);
Through googling I noticed $scope.$apply(); will help me, if so how to use this in above form.
UPDATE 1
Values are changes through jQuery code sitting on HTML page directly:-
<script type="text/javascript">
$(function () {
$('#imgcrop').Jcrop({
onSelect: getcroparea,
aspectRatio: 1 //square selection to crop
});
})
function getcroparea(c) {
$('#hdnx').val(c.x);
$('#hdny').val(c.y);
$('#hdnw').val(c.w);
$('#hdnh').val(c.h);
console.log(c.h + " : " + c.w);
$('#selectedSize').html("Selected region " + c.h + "px : " + c.w + "px");
};
</script>
UPDATE 1
"$scope is not defined" when used
function getcroparea(c) {
$('#hdnx').val(c.x);
$('#hdny').val(c.y);
$('#hdnw').val(c.w);
$('#hdnh').val(c.h);
console.log(c.h + " : " + c.w);
$('#selectedSize').html("Selected region " + c.h + "px : " + c.w + "px");
$scope.$apply();
};

You should wrap both the form and croppable area in a directive.
Here you can access the DOM element that you apply the third-party library to and instead of changing the input text value, change it directly on your scope variable.

There maybe easy solution but I solved this using this:
<script type="text/javascript">
$(function () {
$('#imgcrop').Jcrop({
onSelect: getcroparea,
aspectRatio: 1 //square selection to crop
});
})
function getcroparea(c) {
$('#hdnx').val(c.x);
$('#hdny').val(c.y);
$('#hdnw').val(c.w);
$('#hdnh').val(c.h);
console.log(c.h + " : " + c.w);
$('#selectedSize').html("Selected region " + c.h + "px : " + c.w + "px");
$scope.thumbnail = { "id": $scope.id, "hdnx": c.x, "hdny": c.y, "hdnw": c.w, "hdnh": c.h, "imgcrop": $scope.firstImageSrc };
};
</script>
$scope.thumbnail = .. is new in above code which assigns the scope variable every-time.

Related

Dynamic Javascript output in templated HTML

I am trying to build a Javascript class which takes some options and returns builds a form. I would like the submit function to be determined by the options passed to the class. All of the HTML is output as expected, but I don't think the javascript that is being output is being parsed. When the HTML renders I get a syntax error -
"Unexpected token function"
and when I try to submit the form I get a
Reference error - "{functionName} is not defined."
Here is the class so far:
var ClassOptionsForm = function(options) {
this.options = options
this.getSubmissionFunction = function() {
switch (this.options.type) {
case 'standard':
return this.standardSubmit;
break;
case 'extendable':
return this.extendableSubmit;
break;
}
}
this.successHandler = "function (data, form) {\
$(form).find('.result').text('Success!').css('color', 'green');\
}"
this.failureHandler = "function (data, form) { \
$(form).find('.result').text('Something went wrong.').css('color', 'red');\
}"
this.submitFunctionName = this.options.optionName + "Submit";
this.standardSubmit = "function " + this.options.optionName + "Submit(form) {\
google.script.run\
.withSuccessHandler(" + this.successHandler + ")\
.withFailureHandler(" + this.failureHandler + ")\
.withUserObject(form)\
.setUserOption('" + this.options.optionName + "', form)\
}"
this.extendableSubmit = "function(this) {\
// Extendable Form Submit
}"
this.buildForm = function() {
var value = this.options.value;
return '\
<script type="text/javascript">\
' + this.getSubmissionFunction() + '\
</script>\
<h3>' + this.options.formTitle + '</h3>\
<form id="' + this.options.optionName + '" onsubmit="' + this.submitFunctionName + '(this)">\
' + Object.keys(value).reduce(function(list, key) {
return list + '<input name="' + key + '" value="' + value[key] + '"/>';
}, '') + '\
<button type="submit">Save</button>\
</form>\
'
}
}
And here is how form render function is called in the HTML file:
<?!= GoogleAnalytics().optionsForm.buildForm(); ?>
And here is the final HTML output:
<script type="text/javascript">
function UAIDSubmit(form) {
google.script.run
.withSuccessHandler(function (data, form) {
$(form).find('.result').text('Success!').css('color', 'green');
})
.withFailureHandler(function (data, form) {
$(form).find('.result').text('Something went wrong.').css('color', 'red');
})
.withUserObject(form)
.setUserOption('UAID', form)
}
</script>
<h3>UAID</h3>
<form id="UAID" onsubmit="UAIDSubmit(this)">
<input name="id" value="********">
<button type="submit">Save</button>
</form>
I am pretty sure that this has something to do with the way that App Script sanitizes HTML, and I know there are a million ways I could accomplish submitting the form without dynamic JS. I am just trying to keep my code as dry as possible, and also I'm curious. Any workarounds that keep that don't involve doing away with templated JS?
When you try to submit the form it won't work because you can use a form object as parameter in a Google Script function but the form object must be the only parameter in that function. Read here[1]
[1] https://developers.google.com/apps-script/guides/html/reference/run

variable is not acting independently when using multiple copies of same angular directive

I'm trying to create a directive with 2 radio button binding with update variable. Now I planned to use the same directive in once again. Now the problem is the scoped variable update is not acting independently.
Below is the mock example I have created,
var myApp = angular.module('myApp',['ngRoute']);
myApp.directive('myDirective', function () {
return {
restrict: 'A',
scope: false,
template: '<div><span>A new directive</span>'
+ '<input name="updated" type="radio" ng-model="con.isUpdate" ng-checked="con.isUpdate" />'
+ '<input name="updated" type="radio" ng-model="con.isUpdate" ng-checked="!con.isUpdate" />'
+ '</div>',
controller: controller,
controllerAs: 'con'
};
function controller ($scope) {
$scope.isUpdate = true;
}
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-route.js"></script>
<script src="index.js"></script>
</head>
<body ng-app="myApp">
<div my-directive></div>
<br/>
<div my-directive></div>
</body>
</html>
Running the code snippet will give a clear picture of the problem.
The radio inputs have the same name so the browser is "grouping" them if you will and applying updates to the radios based on name.
An easy way to fix this is to pass the name to the directive to apply to the radios, or (as shown below) create different directives.
function Directive(name) {
return {
restrict: 'A',
scope: false,
template: '<div><span>A new directive</span>'
+ '<input name="' + name + '" type="radio" ng-model="con.isUpdate" ng-checked="con.isUpdate" />'
+ '<input name="' + name + '" type="radio" ng-model="con.isUpdate" ng-checked="!con.isUpdate" />'
+ '</div>',
controller: controller,
controllerAs: 'con'
};
function controller ($scope) {
$scope.isUpdate = true;
}
}
myApp.directive('myDirective', new Directive('updated'));
myApp.directive('myDirective2', new Directive('updated-alt'));

How to call Javascript Function in Angular Js on click Event

I am trying to call Javascript Function in Angular Js on click Event..
Here is the code for click event
listData += '<div class="col-sm-8 padding-left-0 word-wrap"><span class="pros-desc">' + desc + '</span>...<span></span><a href="#" class="redmre ProfilePreview" attr-Location='
+ data.FirmLocation + ' attr-Urlkey=' + data.Urlkey + ' value=' + data.FirmID + ' attr-firm="' + data.FirmName + '" attr-LoginId="'
+ data.LoginId + '">View Profile</a></div><div class="col-sm-1"></div><div class="col-md-4 gap-10"><button type="button" class="bttn btn-green-md btn-BTsm btn-block" onclick="mymodel(' + user + ',' + firm + ')" id="myBtn">GET IN TOUCH</button></div>';
and here is Javascript function ..
function mymodel(user, firm) {
id = user;
name=firm;
}
and here is angular js code
var app = angular.module('myApp', []);
app.controller("customersCtrl", function ($scope, $http, $window) {
var a; // user value must come over here
var b; // firm value must come over here
}
I need user and firm value of Javascript function in my angular js controller but it's not working.
I don't have any other option like I can convert all code in Javascript or angular js, it's small piece of large code so I don't want to change anything else.
I have tried so many options but still it is not working so if anyone can help me out that will be great.
<div ng-click="mymodel(user, firm)"></div>
var app = angular.module('myApp', []);
app.controller("customersCtrl", function ($scope, $http, $window) {
$scope.mymodel = function(a,b){
//do whatever you want to do with values..
}
}

Angular - Can't access controller methods after compiling directive

I am heavily modifying a WYSIWYG js plugin, and am inserting my own custom elements into it.
To insert the custom elements, I am using directives so that they can be easily maintained if I need to make a change. Here is an example of my code so far:
The initial load of the wysiwyg editor:
<div ng-controller="wyswiygCtrl">
<textarea wysiwyg-editor ng-model="content"></textarea>
</div>
Here is an example of a custom element (directive) I am inserting into the wysiwyg content:
<wysiwyg-element class="custom_element" name="awesome" type="checkbox" checked="true"></wysiwyg-element>
I am using the following code within the directive's initialisation, to compile any custom elements (directives) within it:
var e = angular.element(wysiwygEditor.get(0).innerHTML);
$compile(e.contents())(scope);
wysiwygEditor.html(e);
It compiles the directives just as I need it to, but here comes the tricky part. I need to be able to call a function within the 'wysiwygCtrl' from OUTSIDE angular. I am able to do this before compiling, but for some reason, after using angular's compile function, I can't access the scope on the elements.
Here is the code which works before a $compile:
angular.element($('.custom_element')).scope().wysiwygModal();
angular.element($('.custom_element')).scope().$apply();
I get the following error after trying to call the wysiwygModal function after a $compile:
Uncaught TypeError: Object #<Object> has no method 'wysiwygModal'
What am I doing wrong?
I was able to access the scope() and its variables on a compiled element. Could you edit this plunkr or create your own if this doesn't help?
http://plnkr.co/edit/kvbvKXeVjEhmeE7257ly?p=preview
script.js
var myApp = angular.module('myApp', []);
myApp.directive('myEditor', function () {
return {
restrict: 'E',
scope: {
},
template:
'<div>' +
'<h3>Raw HTML</h3>' +
'<textarea rows=5 cols=40 ng-model="text"></textarea>' +
'</div>' +
'<hr />' +
'<div>' +
'<h3>Compiled HTML</h3>' +
'<div my-preview></div>' +
'</div>' +
'<hr />' +
'<div>' +
'<h3>Messages generated during compilation</h3>' +
'<div ng-repeat="message in messages">[{{message}}]</div>' +
'</div>' +
'</div>',
controller: function ($scope) {
$scope.messages = [];
this.getText = function () {
return $scope.text;
};
this.addMessage = function (message) {
$scope.messages.push(message);
};
this.clearMessages = function () {
$scope.messages.length = 0;
};
},
link: function (scope, element, attrs) {
scope.text = '<div ng-init="a = 2" class="my-selector">\n scope.a : [{{a}}]\n</div>';
}
};
});
myApp.directive('myPreview', function ($compile) {
return {
require: '^myEditor',
link: function (scope, element, attrs, myEditorController) {
scope.$watch(myEditorController.getText, function (newValue) {
if (newValue !== undefined) {
var e = angular.element('<div>' + newValue + '</div>');
$compile(e)(scope);
element.html(e);
myEditorController.addMessage(
'The value of "a" on the scope of the compiled element is: ' +
angular.element($('.my-selector')).scope().a)
}
});
}
};
});
index.html
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="angular.js#*" data-semver="1.2.0-rc3-nonmin" src="http://code.angularjs.org/1.2.0-rc.3/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="myApp">
<my-editor></my-editor>
</div>
</body>
</html>

Why won't this variable update?

In the document.ready() I have:
$('#menu_indicator').append('<p>' + currPage + ' / ' + pageLimit + '</p>');
pageLimit is always one number that does not change throughout the whole code.
I have it so that when a user clicks a button, it changes currPage to a different number.
(this part is not in document.ready();)
Why doesn't it update it in the indicator?
Any ideas to fix it?
Thanks
The reason your code doesn't work as you expect it to is that you only append it once, it doesn't attach a 'live' handler or something like it.
If you want the indicator to change each time you set a new value for currPage I'd build a function like so:
function setCurrentPage(page) {
currPage = page;
$("#menu_indicator p").html(currPage + " / " + pageLimit);
}
This is of course assuming currPage and pageLimit are declared on a global scope
Demo for Below Code : http://jsbin.com/oruqa3
HTML :
<input type="button" value="click" />
<div id="menu"></div>
JavaScript :
var currPage = 1, pageLimit = 20;
$(function() {
$('input[type=button]').click(function() {
if(currPage <=pageLimit) {
call();
currPage++;
}
});
});
var call = function() {
$('#menu').html('<p>' + currPage + ' / ' + pageLimit + '</p>');
}

Categories

Resources