Bind click handler to dynamically created DOM elements - angularjs

In my Ionic 2 app I have a template with this code:
<div class="body" [innerHTML]="ticket.Body | safeHtml"></div>
The body is HTML that is returned from a remote API. That HTML can contain images. I want to bind a "click" event handler on those images so that I can open them in an InAppBrowser when a user taps on them.
What would be the best way to do that?
Angular 4.1.3, Ionic 3.3.0

Solution 1
Try binding an event on to the parent to capture clicked target elements.
// HTML file
<div class="body" [innerHTML]="ticket.Body | safeHtml" (click)="bodyDivClick($event)" >
</div>
// TS file
bodyDivClick(event) {
// Check if the clicked target is an Image element.
// You can also check by css class name for specific image elements.
if (event.target && event.target.tagName === 'IMG') {
let imageElem = event.target;
console.log('Image clicked');
}
}
Solution 2
You can also try using ngFor to loop your results (images) into view and bind an event on the image itself.
Assuming that ticket is a JSON parsed object retrieved from the remote API.
<div class="body">
<div *ngFor="let imageUrl of ticket.images; let i = index;" class="image-container" >
<img src="{{imageUrl}}" class="image-style" (click)="imageClick()" />
</div>
</div>
Most probably the first solution might work for you if you are not able to change the response of the Remote API from html to JSON/objects (if it's not implemented by you).

Related

How to make a dynamically retrieved image clickable in angularjs

I have retrieved an image and its corresponding data dynamically, in which I want to make the image clickable which will redirect to a webpage.
How can I achieve this using angularJs.
I am using only angularJs, no jquery.
Below you can see you can assign the values to an object and then use that object on the image tag. If you want to make any other changes on click as well then you can use ng-click as shown below then use $location.url.
$scope.object = {};
$scope.object.filepath = filepath;
$scope.object.redirectURL = redirectURL
<img ng-src="object.filepath" ui-sref="{{object.redirectURL}}" />
$scope.redirect = function(redirectURL)
{
$location.url(redirectURL);
};
<img ng-src="object.filepath" ng-click="redirect(redirectURL)" />
You can use ng-click on the image element. You can handle the click event in your controller where you can navigate to the webpage.
In your controller you can redirect the page to the webpage url.
$scope.goToWebpage = function(imageParam){
window.location.href = "http://UrlToWebpage.com";
}
Alternatively you can wrap the image inside an anchor tag. On clicking the image the page will be redirected to the specified url mentioned in href.
<a href="http://UrlToWebpage.com" >
<img src="sourceToImage" />
</a>

Angular form - img not binding to ng-model

I have a simple angular form that I want to use to send an image to a remote server. I am binding the image src property to a photo pulled from device camera.
But when it's submitted, the image data is empty (ng-model is not binding to the img src attribute). I am having to separately add the image to the form object prior to submitting. Should i have to do that, or can I bind the image data properly to the form?
HTML
<form ng-submit="sendPost(post)">
<img ng-src="{{imageURI}}" ng-model="$parent.post.image"/>
</form>
Controller
$scope.post = {
image: ''
}
$scope.imageURI = //this will be populated with a base64 encoded image pulled from the device camera roll
$scope.sendPost = function(post) {
//i want post.image to have the image data that was sent to the <img> tag via camera when the form is submitted
}
Your idea is too complicated, no need to bind ngModel as <img> is not an Angular directive, but a simple HTML tag.
Option 1
If you want your <form> to submit via Angular/AJAX, there's no need to have the <img>-tag in the form (or have a <form> at all), but I'll leave it in, as I am not sure if you want to show the image prior to submission or not.
Option 2
If you don't want to submit via Angular, you need an <input type="hidden" ng-model="post.imageURI">, but you also need the usual action attribute at the <form>
Back to option 1: just reduce your model to $scope.post, both for the HTML and the Angular code:
HTML
<form ng-submit="sendPost()">
<img ng-src="{{post.imageURI}}"/>
</form>
Controller
$scope.post = {}
$scope.post.imageURI = //this will be populated with a base64 encoded image pulled from the device camera roll
$scope.sendPost = function() {
// need to check here if $scope.post.imageURI is populated
$http.post(
...
data: $scope.post,
....
);
//i want post.image to have the image data that was sent to the <img> tag via camera when the form is submitted
}
In the HTML try change your ng-model from
<img ng-src="{{imageURI}}" ng-model="$parent.post.image />
to
<img ng-src="{{imageURI}}" ng-model="post.image" />
It should work.

Updating a div on collection update in meteor

This is my first meteor app. It's primarily inspired from this blog post. I use ng-switch to display different messages like:
<ng-switch on="message.type">
<!-- Text Widget -->
<div ng-switch-when="text" class="text">
{{ message.text }}
</div>
<!-- Picture Widget -->
<div ng-switch-when="picture" class="picture">
<img ng-click="trackClick($event, message)" ng-src="{{message.picture}}">
</div>
<!-- Dynamic Widget -->
<div ng-switch-when="dynamic" class="dynamic">
<div class="content" ng-click="trackClick($event, message)">{{ message.content }}</div>
</div>
The way this app behaves is as follows:
User enters a text, a meteor collection is updated and the corresponding text widget shows up
A DDP client (in Ruby) listens for any add event in the collection. It updates the collection with a text or image or dynamic content.
The frontend creates a new DOM element and displays the content in that element.
However, I have a special content type called dynamic where I do not want to create a new DOM element (everytime), but rather edit the content of existing DOM element.
The way I think to achieve this is to edit the corresponding Mongo entry without adding a new one. But is there a way I could have this functionality when I have to add a new entry?

AngularJs app does not bind data to DOM

I have created simple angularJS app.I used ng-repeat to bind data to DOM
<div class="row folder" ng-repeat="f in viewModel.folders">
<div>{{f.name}}</div>
</div>
so weird ,my data not bind to DOM until I click any button with "ng-click" action.
I do not know why ?
I resolved myself by call $scope.apply() at the end.

AngularJS's ng-model icm textarea

I'm trying to add some text to the last cursor place after clicking a button.
In the controller:
$scope.addEmoji = function(name){
var element = $("#chat-msg-input-field");
element.focus(); //ie
var selection = element.getSelection();
var textBefore = $scope.chatMsg.substr(0, selection.start);
var textAfter = $scope.chatMsg.substr(selection.end);
$scope.chatMsg = textBefore + name + textAfter;
}
$scope.updateChatMsg = function(chatMsg){
$scope.chatMsg = chatMsg;
}
$scope.sendChatMsg = function(){
var backend = $scope.convs[$scope.active.conv].backend.name;
$scope.view.addChatMsg($scope.active.conv, $scope.active.user, $scope.chatMsg,new Date().getTime() / 1000, backend);
Chat[backend].on.sendChatMsg($scope.active.conv, $scope.chatMsg);
$scope.chatMsg = '';
};
And then some HTML:
<div class="chat-msg-button" >
<button ng-click="view.toggle('emojiContainer')" ><img src="/apps/chat/img/emoji/smile.png"></button>
</div>
<form id="chat-msg-form" ng-submit="sendChatMsg()">
<div class="chat-msg-button" >
<button type="submit"><div class="icon-play"> </div></button>
</div>
<div id="chat-msg-input">
<textarea id="chat-msg-input-field" autocomplete="off" type="text" ng-model="chatMsg" ng-change="updateChatMsg(chatMsg)" placeholder="Chat message"></textarea>
<div>{{ chatMsg }}</div>
</div>
</form>
What I'm trying to achieve: a user types some text in the textarea => $scope.chatMsg gets the value of the textarea. Now the user press one of the button's => the name of the button is added to the latest cursor position. (it's no problem to find the latest cursor position)
The problem
There is a difference between the value of $scope.chatMsg, {{ chatMsg }} inside the div and the text in the textarea.
The contents of the textarea and the div stays always the same. But when pressing the button the name is added to $scope.chatMsg but the contents of the textarea isn't changed...
How can I solve this?
TIA
First of all, you're mixing jQuery with AngularJS, it doesn't look like you need jQuery here that much.
Also, your chat message is updated in 3 different functions, so you need some debugging to see which are fired.
In general:
To solve your issue, try some more debugging, do a
$scope.$watch($scope.chatMsg, function(){
console.log($scope.chatMsg);
});
this will watch all changes to chatMsg. Add console.log() to each of your functions and you can watch which is fired.
Also, rather than using {{ }} inside your div just use ng-bind since that text is the only item in your div, it's cleaner if your app crashes somewhere.
// change from
<div>{{ chatMsg }}</div>
// to
<div ng-bind="chatMsg "></div>
Update: after seeing your plunker, I modified it and came up with this: http://plnkr.co/edit/oNKGxRrcweiJafKCm9A5?p=preview
Your ng-repeat needs to be tracked by $index so that duplicates are displayed rather than crashing when someone creates the same message
I solved all problems. The plunkr form above works. So after investigating all scopes with the Angular chrome extension I saw that chatMsg was defined in another scope. Thus not in the scope I was trying to acces it from.
Via this question angularJS ng-model input type number to rootScope not updating I found a solution.
I added chatMsg to the fields object.

Resources