Angular update ng-model in ng-repeat - angularjs

Basically, I am trying to figure out a way to return a selected value (say, from a modal) to a specific model, when that model may be dynamically generated via ng-repeat.
So this is what my data looks like:
{
"title": "Example Title",
"enabled": true,
"thumbnailImage": "file1.png",
"content": [{
"order": 0,
"type": "wysiwyg",
"content": "<div>This is wysiwyg content!</div>"
},
{
"order": 1,
"type": "image",
"content": "file2.png"
}],
"id": 1
}
Now, the user can keep generating additional content by clicking a button that adds a new object with their selected type to the 'content' array. So an article may have one content image, or a hundred, or none (but will always have the 'thumbnailImage').
Using https://github.com/nervgh/angular-file-upload, I have added a modal which allows users to either upload a new image file, or select an existing image from the server. So my HTML looks a bit like this (for the ng-repeat content - similar for thumbnailImage):
<div class="Control">
<label>Content</label>
<div class="panel panel-default" ng-repeat="block in article.content">
<div class="panel-body">
<!-- ... other content types here ... -->
<div ng-if="block.type == 'image'">
<input type="text"
ng-model="block.content"
ng-if="block.type == 'image'"
class="form-control"
>
<a ng-click="selectImage()" class="btn btn-primary">Select image</a>
<button type="button" ng-if="!!activeImage" ng-click="block.content = activeImage" class="btn btn-secondary">Insert image</button>
</div>
</div>
</div>
</div>
selectImage() opens the modal, populates it with all the files already uploaded to the server, and has a drag-and-drop section allowing users to upload new images.
The modal looks like this:
<div ng-if="showFileManager" nv-file-drop uploader="uploader">
<div class="row">
<div ng-repeat="file in files" class="col-3">
<img ng-src="/{{ file.container }}/{{ file.name }}" ng-click="setActiveImage( file )">
</div>
</div>
<div ng-show="uploader.isHTML5">
<div nv-file-over uploader="uploader">
Drag and drop images to upload
</div>
</div>
</div>
What I am trying to do is on selecting an image, instantly populate the text input related to the 'selectImage()' button.
At the moment, clicking an image fires 'setActiveImage()', which is:
$scope.setActiveImage = function( file ) {
var filePath = 'http://localhost:3000/uploads/' + file.container + '/' + file.name;
$scope.activeImage = filePath;
};
And then the 'Insert image' button next to the 'Select image' button under each image updates the model. However, I'm hoping to be able to do that in the modal so all the user has to do is click the 'Close' modal button and the field is populated.
Does this make sense, and is it possible?

The way I get a specific item of ng-repeat is to pass it to a function in my view.
<html element ... useSelectedFile(file)></html element>
Then in your controller:
$scope.useSelectedFile = useSelectedFile;
function useSelectedFile(file){
//do stuff
//call function
//set scope item in view to file
}

Related

Ng-Repeat and Angular Filters

I have an array of "action" objects. Each object has a status: "mastered" or "new".
On one nav-tab, I show the "new" actions:
<div ng-repeat="x in main.actions | filter: {status: '!mastered'} >
<div class="btn-group">
<label ng-model="x.status" uib-btn-radio="'new'"><label>
<label ng-model="x.status" uib-btn-radio="'mastered'"></label>
</div>
</div>
On a separate nav-tab, I show the mastered actions. My code there is identical with the exception of the filter included in the ng-repeat.
By clicking on these radio buttons, one can change the status of an action from "new" to "mastered." Everything works as intended, however, when I change the status of an action, the entire SPA returns to it's main page!
Why is that? What do I need to do to prevent that from happening?
You can consolidate so you don't have to necessarily use a different tab for each status.Try something like this.
Code:
<div ng-repeat="x in main.actions | filter: {status: stat} "></div>
<div class="btn-group">
<label ng-model="x.status" uib-btn-radio="'new'" ng-click="stat = 'new'"><label>
<label ng-model="x.status" uib-btn-radio="'mastered'" ng-click="stat = 'mastered'"></label>
</div>
This should now filter your ng-repeat based on the button you click.

Pass Null of a Data to Angular-Jasny-Bootstrap

I am using file input of jasny-boostrap in AngularJS in a Modal, so I also used the jasny-bootstrap-angular. I am having two doubts about:
When I Click on the button to open the model, I am able to select then file I want. If I select a file e close the model, when I open again the model, the file will be in data-preview, it it not cleaning up. I want pass null value (or reset) this image preview (fileinput-preview thumbnail) in my angularjs when I click in my button to open the modal;
If a click in a button that call a modal, I want to automatic get the image from my web service to the data-previw and automatic change the buttons to 'remove' and 'change' and I get a picture to service.
My HTML:
<div class="fileinput fileinput-new" data-provides="fileinput">
<div class="fileinput-preview thumbnail" style="width: 200px; height: 150px;"></div>
<div>
<span class="btn btn-primary btn-file">
<span class="fileinput-new">Select a image</span>
<span class="fileinput-exists">Change</span>
<input type="file" name="file" file-model="fileinput"> <!--compose.myFile-->
</span>
Remover
<button class="btn btn-info" ng-click="showInput()">Show Input</button>
</div>
</div>
And if I click on 'show input' I can see the image binary, I used this angularjs:
$scope.showInput = function () {
console.log($scope.fileinput.result);
}
I am using this HTML code with my angularjs to see the image from web service and it is everything work perfect:
<!-- Foto view-->
<div class="form-group">
<img ng-show="equipamento.FotoEquipamento != null" style="height:auto; width:225px;" data-ng-src="{{getImage(equipamento.FotoEquipamento)}}" />
</div>
jasny-bootstrap-angular is UPDATED.
Please check it out.
Now it supports event handlers also.

AngularJS Expression Not Working Correctly in ng-src with JSF

The angularjs module. the products array contains 2 product objects that will be added as a property of the controller.
(function () {
var app = angular.module('myApp', []);
var products = [
{
title: "Dummy Title 1",
description: "Dummy Description 1",
image: "dummy_image_1.jpg"
},
{
title: "Dummy Title 2",
description: "Dummy Description 2",
image: "dummy_image_2.jpg"
}
];
app.controller('myController', function () {
this.products = products;
});
})();
The JSF Page, if I remove images/{{product.image}} with the actual image file name such as images/dummy_image_1.jpg, the images are displayed, but if I use angularjs expression instead, then nothing is shown. Please note that other expressions in the loop work besides {{product.image}}. If I add {{product.image}} somewhere else, then it displays the filename correctly, but used in ng-srs, it prints nothing if I view the html. I don't know why it is.
<h:form>
<div class="container" ng-controller="myController as controller">
<div class="row">
<div class="col-sm-offset-10">
Hello <b><h:outputText value="#{user.userName}"/></b><br/>
<h:commandLink action="cart" value="Cart"/>
</div>
</div>
<hr/>
<div ng-repeat="product in controller.products">
<div class="row">
<div class="media">
<div class="media-left">
<img class="media-object" ng-src="images/{{product.image}}"/> <!--If I replace that expression with a the image file name, it shows the image -->
</div>
<div class="media-body">
<h4 class="media-heading">{{product.title}}</h4>
<span class="caption">{{product.description}}</span><br/>
<h:commandLink action="cart" value="Add to cart"/>
</div>
</div>
</div>
</div>
</div>
</h:form>
Sometimes using interpolation {{}} won't evaluate & update value of attribute (most often this happens in IE). The way to do this is using ng-src directive with interpolation {{}} this will add src to the img tag after evaluation interpolation directive.
Markup
<div class="media-left">
<img class="media-object" ng-src="{{'images/'+product.image}}"/>
<!--If I replace that expression with a the image file name, it shows the image -->
</div>
Alternative
The other way would be using ng-attr directive which add attribute with evaluated value. This will ensure you everytime that the interpolated value has been assigned to the attribute mentioned it in ng-attr (the part after ng-attr is considered as attribute to be added, suppose we have ng-attr-value="{{someVar}}" then angular will evaluate someVar and then assign that value to value attribute on that element.
Markup
<div class="media-left">
<img class="media-object" ng-attr-src="{{'images/'+product.image}}"/>
<!--If I replace that expression with a the image file name, it shows the image -->
</div>

How to show preloader inside button instead text Angular JS?

I use Angular JS library ngActivityIndicator.
I tried to show preloader inside element div instead text when button is pushed:
<div ng-activity-indicator="CircledDark">
<div ng-click="Add();" class="btn shareBtn">
<div ng-view></div>
<span>Text</span>
</div>
</div>
I posted <div ng-view></div> inside and have added directive ng-activity-indicator="CircledDark" to parent element.
When I click button, I call function that display preloader:
$activityIndicator.startAnimating();
But preloader is created outside of button:
<div ng-show="AILoading" class="ai-circled ai-indicator ai-dark-spin"></div>
This is official documantation, from here I have taken example:
https://github.com/voronianski/ngActivityIndicator#directive
How to show preloader inside button instead text Angular JS?
I think the only solution is to separate your ng-view and button, at least they do something similar in their sample page. So, in your markup you could do something like this:
<div ng-click="add()" class="btn btn-default" ng-activity-indicator="CircledDark">
<span ng-show="!AILoading">Add</span>
</div>
<div ng-view ng-show="!AILoading">{{ delayedText }}</div>
And in your controller:
$scope.delayedText = "";
$scope.add = function() {
$activityIndicator.startAnimating();
$timeout(function() {
$scope.delayedText = "Here we are!";
$activityIndicator.stopAnimating();
}, 3000);
};
Here is full Demo, you can play with CSS a little so the size of the button won't change when text is replaced by icon.

[Angular JS]- Tabs Pane Example - Dynamic Add Tab

I have used the example from Angular JS Homepage and modified it to meet the requirements.
I have added the tabs info in a scope array and manipulate the data based in some conditions.
Issues:
I have attached an ng-bind on tabItem.title, so any change in the text box will update the title, but i want to limit the displaying of the title by 10 chars
When i create a new tab, i want that tab to be the selected one.
How can i select a tab based on some action taken (like on a click move from tab 1 to tab 2)
Fiddle: http://jsfiddle.net/austinnoronha/NWwcT
<br/><br/>
<div ng-cloak ng-app="TabsApp">
<div class="container" ng-controller="TabManagerCtrl">
<span class="label label-info label-ext" ng-click="tabManager.addTab()" style="cursor:pointer">Add a Tab</span><br/><br/>
<div>
<div tabs>
<div ng-repeat="tabInfo in tabManager.tabItems" pane title="{{ tabInfo.title }}">
<p>{{ tabInfo.content }}</p>
<input type="text" ng-model="tabInfo.title" ng-change="tabManager.getTitle(tabInfo)">
</div>
</div>
</div>
<br/><br/><br/>
</div><!-- /container -->
</div> <!-- /container -->
</div> <!-- /app -->
that's strange...
The limitTo filter doesn't seem to work, but you can create a new one and change your line
<div ng-repeat="tabInfo in tabManager.tabItems" pane title="{{ tabInfo.title }}">
by
<div ng-repeat="tabInfo in tabManager.tabItems" pane title="{{ tabInfo.title | limit:10}}">
with
angularApp.filter('limit', function() {
return function (input, value) {
return input.substr(0,value);
};
});
For the select one, I think it doesn't work because you have to have access to the pane scope. One way to do it is to access to access the property from the pane when you create it. In the pane directive, just add :
if(scope.$parent.tabInfo.selected) tabsCtrl.select(scope);
just after the tabsCtrl.addPane(scope); line. But then you also have to change the tabs directive so that the line
$scope.select = function(pane) {
become
this.select = $scope.select = function(pane) {
For your 3rd question, I don't know how to do it in that scheme.
I would make the pane directive different, putting the select function out of the directive, and binding it directly to your tabManager object.
Like this : http://jsfiddle.net/NWwcT/2/
In this cas, you have the 3 requirements, and you can select the tab from ouside by calling tabManager.select(index)

Resources