Angular form - img not binding to ng-model - angularjs

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.

Related

Bind click handler to dynamically created DOM elements

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).

Binding raw object output to a form representation

I'm trying to update models from a JSON representation of an object to a form. Here's a link to an example
To recreate my issue,
Change the data in the form (see that the JSON changes).
Change the JSON (See that the form doesn't change).
Here's my code:
JS
var ppl = {
createdby: "foo",
dateCreated: "bar",
}
angular.module('myApp', [])
.controller("Ctrl_List", function($scope) {
$scope.people = ppl
$scope.print = JSON.stringify($scope.ppl)
})
HTML
<div ng-app="myApp">
<div class="container" ng-controller="Ctrl_List">
<!-- FORM -->
<div class="row" ng-repeat="(key,val) in people track by $index">
<div class="col-md-12">
<label for="{{key}}">{{key}}</label>
<input class=form-control" id="{{key}}" ng-model="people[key]">
</div>
</div>
<!-- JSON -->
<div class="editable" contenteditable="true" ng-model="people">{{people}}</div>
</div>
</div>
When a user changes the JSON, the form should update in real-time.
Here's some things I have tried:
Change the JSON display element from div to input but it prints [Object][Object]
Also <input ng-model="JSON.stringify(people)"> but I get an "unbindable element" error.
Also tried adding a new model: $scope.print = JSON.stringify(people) but it shows nothing in the raw output.
Is it even possible to update a live object or am I gonna have to do some sort of event that triggers the form to change?
PS: Angular 1.5.8
There are several reasons why this doesn't work:
ng-model on a div doesn't do anything
even if it did, it would save a string to people, and your form would thus not work anymore.
You should use a textarea to make it work, and bind it to another variable, of type string. Using ng-change on the textarea, and on the inputs of the form, allows populating the people object by parsing the JSON string, and vice-verse, populating the JSON string from the people object.
See https://codepen.io/anon/pen/peexPG for a demo.
Refering to Contenteditable with ng-model doesn't work,
contenteditable tag will not work directly with angular's ng-model because the way contenteditable rerender the dom element on every change.

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>

How to create form in Angular JS?

There is block HTML with article:
<div class="block">
<span ng-click="edit()">Click</span>
<div class="title">How to</div>
<div class="text">Text</div>
</div>
When I call edit function ng-click="edit()" I call AJAX that returns data:
title
text
These data I set in $scope:
$scope.title = title;
$scope.text = text;
How I can create form with input, textarea instead HTML in .block?
I neeed to switch on edit mode and display form for editing.
You are essentially asking how to do a form. I would try going through some examples from the documentation eg. https://docs.angularjs.org/api/ng/directive/form
paying key attention to the ng-model="" tags to bind your data fields. Then the scope variables should automatically update your form.

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