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..
}
}
Related
Can someone please assist me here. I getting a list of POSTS from a wordpress api(get_posts). Once I get the posts, I am displaying them in a list of <a> tags. In every <a> tag there is a title and description of the post item. All of this is done dynamically in javascript within the ionic framework.
Here comes my issue. Once the list of posts are shown I need to click on a single post item from my list which then needs to show me more details (i.e. Excerpt) from it. However I am only succeeding in showing every posts details and not only the selected one. I am showing the Excerpt in a modal.
My code is below.
Javascript
//call JSON API upon page enter //gets list of posts and populates them in tags // tags have have title and description added
.controller('chickenCtrl', function($scope, $stateParams, $window, $http, $state, $ionicModal, $ionicLoading) {
$scope.$on('$ionicView.enter', function(){
$scope.result = "";
$scope.categories = "";
$http.get('http://dhameergovind.co.za/wp/api/get_posts/')
.success(function(data, status, headers,config){
var i;
var j;
for (i = 0; i < data.posts.length; i++) {
console.log(data.posts[i]);
var image = data.posts[i].thumbnail;
var post_id = data.posts[i].id;
console.log(post_id);
for (j = 0; j < data.posts[i].categories.length; j++){
if (data.posts[i].categories[j].title=="Chicken"){
var chickenTitleObj = data.posts[i].title;
var chickenDescObj = data.posts[i].content;
document.getElementById('chick').innerHTML += '<a class="item item-thumbnail-left item-block" + id='+i+'>' + '<img src ="' + image + '"/>' + '<div class="middleText">' + '<h3 class="text-wrap">' + chickenTitleObj + '</h3>' + '<p class="text-wrap">' + chickenDescObj + '</p>' + '</div>' + '</a>' + '<br/>';
}
else{
alert("not existing")
}
}
}
$scope.result = data; // for UI
})
.error(function(data, status, headers,config){
console.log('data error');
$ionicLoading.hide();
})
.then(function(result){
things = result.data;
$ionicLoading.hide();
});
});
//once a post is clicked a modal opens to display details(Excerpt) of selected post
$ionicModal.fromTemplateUrl('templates/recipeModal.html', { scope: $scope }).then(function(modal) { $scope.modal = modal; })
$scope.$on('modal.shown', function(e) {
$ionicLoading.show({
content: 'Loading',
animation: 'ripple',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
$scope.result = "";
$scope.categories = "";
$http.get('http://dhameergovind.co.za/wp/api/get_posts/')
.success(function(data, status, headers,config){
var i;
for (i = 0; i < data.posts.length; i++) {
console.log(data.posts[i]);
var image = data.posts[i].thumbnail;
var post_id = data.posts[i].id;
console.log(post_id);
var chickenTitleObj = data.posts[i].title;
var chickenDescExerptObj = data.posts[i].excerpt;
document.getElementById('chickDesc').innerHTML += '<a class="item item-thumbnail-left item-block">' + '<img src ="' + image + '"/>' + '<div class="middleText">' + '<h3 class="text-wrap">' + chickenTitleObj + '</h3>' + '<p class="text-wrap">' + chickenDescExerptObj + '</p>' + '</div>' + '</a>' + '<br/>';
$ionicLoading.hide();
}
$scope.result = data; // for UI
})
.error(function(data, status, headers,config){
console.log('data error');
$ionicLoading.hide();
})
.then(function(result){
things = result.data;
$ionicLoading.hide();
});
});
})
//HTML
<ion-view view-title="Chicken Recipes">
<ion-content>
<div class="list">
<div id="chick" class="input-box" ng-click="modal.show()">
</div>
</div>
</ion-content>
</ion-view>
//Modal HTML
<ion-modal-view view-title="Chicken Recipes">
<ion-content class="padding">
<div class="list">
<div id="chickDesc" class="item-block input-box">
</div>
</div>
<button class="button button-block button-positive" ng-click="modal.hide()">Close</button>
</ion-content>
</ion-modal-view>
Your ng-click is on the entire list of results, so you have no way of knowing what was clicked. You need it to be on one of the repeated elements, and you need some way to know which one was clicked, like this:
document.getElementById('chickDesc').innerHTML += '<a ng-click="item_clicked(' + i.toString() + ');" class= ...
Define item_clicked in your controller like this:
$scope.item_clicked = function(index) {
$scope.clicked_index = index;
$scope.modal.show();
};
Now in your on-modal-shown, remove the for loop and just leave its body, substituting $scope.clicked_index instead of each use of i.
Also, you shouldn't call $http.get('http://dhameergovind.co.za/wp/api/get_posts/') again. It's inefficient, and might also cause you to see the wrong data, in case new posts have been added and the indexes don't match up. Instead, save the data the first time you get it in your success function in on-enter. Something like this:
$scope.posts = data
Optionally, and a bit more advanced, you could make an endpoint like http://dhameergovind.co.za/wp/api/get_posts/{post_id} to get just one post. That would make sure you have the latest data on the post you selected.
As the comment above said, you really aren't using the maximum power of Angular. With Angular, you shouldn't need to use Javascript to build the structure of your page. Writing HTML strings in your Javascript code is a sign that you're doing it wrong. Even manipulating the DOM is probably not the best way. With Angular, your Javascript code should just retrieve, send, and manipulate data, and your template should describe how that's mapped to document structure.
But my answer is the smallest change you can do to your code to make it do what you want.
Why are you looping to display details in your modal? Also you don't need to call your URL again to get data every time you need to show modal window. Just keep the loaded data in a variable and use it for all subsequent clicks.
I assume you are opening the modal window based on user clicking the link. You already defined an id (if you think it is not unique then make it unique) for these links. That id is nothing but index for your array element which needs to be shown on modal window. Just get the array element and set the details to your chickDesc.
I have been playing around with Angular Material and I wanted to create a $mdDialog that allows a user to enter in information that when saved, will update an object tied to a ng-repeat.
While trying to get this to work and trying out different parameters for mdDialog.show() I was confused about what scope is being used when/why.
This is the first implementation:
(function () {'use strict';
angular.
module('myApp', ['ngMaterial']).
controller('AppCtrl', AppCtrl);
function AppCtrl($mdDialog, $scope) {
$scope.lister = [{name:'Matt'},{name:'Steve'}];
$scope.showDialog = showDialog;
function showDialog(evt) {
$scope.obj = {name:'default'};
$mdDialog.show({
targetEvent: evt,
scope: $scope.$new(),
template:
'<md-dialog>' +
' <md-content><md-input-container>'+
' <label>Name</label>'+
' <input ng-model="obj.name">' +
' </md-input-container></md-content>' +
' <div class="md-actions">' +
' <md-button ng-click="close(obj)">' +
' Save' +
' </md-button>' +
' </div>' +
'</md-dialog>'
}).then(function(objs){$scope.lister.unshift(objs)});
}
$scope.close = function(objs){
$mdDialog.hide(objs);
}
}
}());
The behavior of the above code is mdDialog will open with "default" in the Name input field, but if I change the show() parameters to below (key difference is swapping out "scope:" for "controller:"):
function showDialog(evt) {
$scope.obj = {name:'default'};
$mdDialog.show({
targetEvent: evt,
controller: 'AppCtrl',
template:
'<md-dialog>' +
' <md-content><md-input-container>'+
' <label>Name</label>'+
' <input ng-model="obj.name">' +
' </md-input-container></md-content>' +
' <div class="md-actions">' +
' <md-button ng-click="close(obj)">' +
' Save' +
' </md-button>' +
' </div>' +
'</md-dialog>'
}).then(function(objs){$scope.lister.unshift(objs)});
}
The behavior of the second implementation is that the mdDialog will open with a blank for the Name input field.
This is a long setup for this question: Why does the dialog template recognize $scope.obj when "scope: $scope.$new()", but it is not recognized when "controller: 'AppCtrl'"? I thought both implementations are providing AppCtrl's scope to the dialog.
Dialog is always given an isolated scope
You can pass data to dialog from parent controller using dependency injection.
function AppController($scope, $mdDialog) {
var message='message from parent';
$scope.showDialog = showDialog;
$scope.items = [1, 2, 3];
function showDialog($event) {
var parentEl = angular.element(document.body);
$mdDialog.show({
parent: parentEl,
targetEvent: $event,
templateUrl:'templateFile.html',
locals: {
items: $scope.items
},
message:message
controller: DialogController
});
function DialogController($scope, $mdDialog, items,message) {
$scope.items = items;
$scope.message = message;
$scope.closeDialog = function() {
$mdDialog.hide();
}
}
}
In your first case, you are adding an object to isolated scope of your dialog using
$scope.obj = {name:'default'} and its available as obj.name on yr view.
In your second case, you are declaring controller for your dialog as 'AppCtrl', but you have not defined it anywhere inside your parent controller, so you are not getting anything on view. AppCtrl is not defined.
if you want to use calling scope; you can pass 'isolateScope' parameter like this:
$mdDialog.show({
....,
isolateScope: false
});
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.
I have the following directive that my application is using. I was under the impression that my application was working fine with AngularJS 1.3 but after a lot of changes including a move to the latest version, the removal of jQuery, and also the use of controller as then now this directive is giving me errors:
app.directive('pagedownAdmin', function ($compile, $timeout) {
var nextId = 0;
var converter = Markdown.getSanitizingConverter();
converter.hooks.chain("preBlockGamut", function (text, rbg) {
return text.replace(/^ {0,3}""" *\n((?:.*?\n)+?) {0,3}""" *$/gm, function (whole, inner) {
return "<blockquote>" + rbg(inner) + "</blockquote>\n";
});
});
return {
require: 'ngModel',
replace: true,
scope: {
modal: '=modal'
},
template: '<div class="pagedown-bootstrap-editor"></div>',
link: function (scope, iElement, attrs, ngModel) {
var editorUniqueId;
if (attrs.id == null) {
editorUniqueId = nextId++;
} else {
editorUniqueId = attrs.id;
}
var newElement = $compile(
'<div>' +
'<div class="wmd-panel">' +
'<div data-ng-hide="modal.wmdPreview == true" id="wmd-button-bar-' + editorUniqueId + '"></div>' +
'<textarea data-ng-hide="modal.wmdPreview == true" class="wmd-input" id="wmd-input-' + editorUniqueId + '">' +
'</textarea>' +
'</div>' +
'<div data-ng-show="modal.wmdPreview == true" id="wmd-preview-' + editorUniqueId + '" class="pagedownPreview wmd-panel wmd-preview">test div</div>' +
'</div>')(scope);
iElement.html(newElement);
var help = function () {
alert("There is no help");
}
var editor = new Markdown.Editor(converter, "-" + editorUniqueId, {
handler: help
});
var $wmdInput = iElement.find('#wmd-input-' + editorUniqueId);
var init = false;
editor.hooks.chain("onPreviewRefresh", function () {
var val = $wmdInput.val();
if (init && val !== ngModel.$modelValue) {
$timeout(function () {
scope.$apply(function () {
ngModel.$setViewValue(val);
ngModel.$render();
});
});
}
});
ngModel.$formatters.push(function (value) {
init = true;
$wmdInput.val(value);
// editor.refreshPreview();
return value;
});
editor.run();
}
}
});
Can someone explain to me what the following is doing:
scope: {
modal: '=modal'
},
and also the
)(scope);
Here is how I am calling this directive:
<textarea id="modal-data-text"
class="pagedown-admin wmd-preview-46"
data-modal="modal"
data-pagedown-admin
ng-model="home.modal.data.text"
ng-required="true"></textarea>
If anyone can see anything that may not work in 2 then I would much appreciate some help. In particular it seems that the following code returns null:
var $wmdInput = iElement.find('#wmd-input-' + editorUniqueId);
You dropped jQuery, so your code now relies on jQLite. Functions of element objects support less functionality when using jqLite. See the full details in the doc:
https://docs.angularjs.org/api/ng/function/angular.element
var $wmdInput = iElement.find('#wmd-input-' + editorUniqueId);
Under jqLite, the find function only support searching by tag names, ids will not work. You can use the following tricks from ( AngularJS: How to .find using jqLite? )
// find('#id')
angular.element(document.querySelector('#wmd-input-' + editorUniqueId))
$compile is a service that will compile a template and link it to a scope.
https://docs.angularjs.org/api/ng/service/$compile
scope: {
modal: '=modal'
}
allows you to define a isolated scope for the directive with some bindings to the scope in which the directive is declared. '=' is used for two-way data bindings. Other options are '# and &' for strings and functions.
https://docs.angularjs.org/guide/directive
I stumbled upon this article on how to build a click to edit feature for a form. The author states:
What about if you wanted input type="date" or even a select? This
is where you could add some extra attribute names to the directive’s
scope, like fieldType, and then change some elements in the template
based on that value. Or for full customisation, you could even turn
off replace: true and add a compile function that wraps the necessary
click to edit markup around any existing content in the page.
While looking through the code I cannot seem to wrap my head around how I could manipulate the template in such a way that I could make it apply to any angular component, let alone how I can make it apply to a drop down list. Code from article below:
app.directive("clickToEdit", function() {
var editorTemplate = '<div class="click-to-edit">' +
'<div ng-hide="view.editorEnabled">' +
'{{value}} ' +
'<a ng-click="enableEditor()">Edit</a>' +
'</div>' +
'<div ng-show="view.editorEnabled">' +
'<input ng-model="view.editableValue">' +
'Save' +
' or ' +
'<a ng-click="disableEditor()">cancel</a>.' +
'</div>' +
'</div>';
return {
restrict: "A",
replace: true,
template: editorTemplate,
scope: {
value: "=clickToEdit",
},
controller: function($scope) {
$scope.view = {
editableValue: $scope.value,
editorEnabled: false
};
$scope.enableEditor = function() {
$scope.view.editorEnabled = true;
$scope.view.editableValue = $scope.value;
};
$scope.disableEditor = function() {
$scope.view.editorEnabled = false;
};
$scope.save = function() {
$scope.value = $scope.view.editableValue;
$scope.disableEditor();
};
}
};
});
My question is, how can we extend the above code to allow for drop down edits? That is being able to change to the values that get selected.
One approach you might consider is using template: function(tElement,tAttrs ).
This would allow you to return appropriate template based on attributes.
app.directive("clickToEdit", function() {
return {
/* pseudo example*/
template: function(tElement,tAttrs ){
switch( tAttrs.type){
case 'text':
return '<input type="text"/>';
break;
}
},....
This is outlined in the $compile docs