Send array from modal component to previous component and show result - Angular - arrays

Problem: I have a button in a form that opens a modal window(a component). In this modal window the user selects the files he wishes to upload. After the clicks in button submit in the modal window. It closes the modal and stays in the previous component. I need to take the name of the files selected to the previous component and show to the user.
The modal html
In here i have the modal html where the user selects which files he wants to upload.
After that he clicks in submit and is sending the names of the files to an array.
<div class="modal-dialog modal-lg">
<div class="modal-header">
<h4 class="modal-title">Selecionar Assets</h4>
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group text-center">
<input type="file" name="image" (change)="onSelectFile($event)" multiple />
</div>
<div class="row">
<div class="col">
<p class="text-center h4">Asset</p>
</div>
<div class="col">
<p class="text-center h4">Name</p>
</div>
</div>
<div class="row" *ngFor='let url of urls let i = index'>
<div class="col">
<div class="text-center image-preview img-responsive mb-3">
<img [src]="url" height="100" width="100"/>
</div>
</div>
<div class="col trimText">
<div class="text-center mb-3">
<p class="text-center"> {{ names[i] }}</p>
</div>
</div>
</div>
<div class="form-group text-center">
<button class="btn btn-primary" (click)="onSubmit(); activeModal.dismiss('Cross click')">Submit</button>
</div>
</div>
</div>
The modal component.ts
In here I'm iterating over the multiple files the user selected and get the name of those files.
When clicked on the button submit i send that array to the component that opens the modal.
#Input() names:Array<string> = [];
#Output() namesEntry: EventEmitter<string[]> = new EventEmitter();
onSelectFile(event) {
if (event.target.files && event.target.files[0]) {
var filesAmount = event.target.files.length;
for (let i = 0; i < filesAmount; i++) {
this.names.push(event.target.files[i].name);
var reader = new FileReader();
reader.onload = (event:any) => {
this.urls.push(event.target.result);
}
reader.readAsDataURL(event.target.files[i]);
}
console.log(this.names);
}
}
onSubmit() {
//send to form name of the assets
this.activeModal.close(this.names);
}
The form html
In this part of the component is where I want to show the name of the files that i had in the modal. The problem is that is never showned, even and the array names is not empty and the isActive is true
<div id="assets" class="text-center" *ngIf="isActive; else notActive">
<ng-template #notActive>
<div *ngFor='let name of names'>
<p class="h6">{{name}}</p>
</div>
</ng-template>
</div>
The form component.ts
Here is where I retrieve the array of names from the modal to this component and when i do console.log of this.names return the array with the names and this.isActive returns true.
names:Array<string> = [];
isActive = false;
constructor(private modalService: NgbModal) {}
open() {
const modalRef = this.modalService.open(AssetComponent, {size:"lg", backdrop: 'static'});
modalRef.componentInstance.title = 'asset';
modalRef.result.then((result) => {
if (result) {
this.names = result;
this.isActive = true;
}
});
}

Please change the code to following.
<div id="assets" class="text-center" *ngIf="isActive">
<div *ngFor='let names of names'>
<p class="h6">{{name}}</p>
</div>
</div>
Your condition was wrong. It will not render the data because of isActive flag set to true and template was set to render when the isActive flag is false.
Keep in mind, Template(<tempalte #ref></template>) inside the *ngIf will only available when the condition is met.
For example,
<div *ngIf="test else nodData">
Data Available
<template #nodData>No Data available</template>
</div>
Template nodData will not be available unit the ngIf condition met. So the noData wont display. So always keep the ref outside ngIf block for else conditions
<div *ngIf="test else nodData">
Data Available
</div>
<template #nodData>No Data available</template>

Please update your template to render correctly,
In *ngIf condition, template should be outside the condition element
<div id="assets" class="text-center" *ngIf="isActive; else notActive">
<div *ngFor='let names of names'>
<p class="h6">{{name}}</p>
</div>
</div>
<ng-template #notActive>
// Your message or code
</ng-template>

Related

Providing action to only the clicked button in ng-repeat

I'm working with ng-repeat .In the ng-repeat i'm repeating panel.The panel body consist of two part .First part is a paragragh which i fetch from the database using $http.get(). In the second part i have a button (edit button).When i click the edit button the paragraph in the first part should be hidden and text-area should appear with the content in the paragraph as default.But when i'm trying to achieve this im getting an idea when i click one edit button all of my paragragh hides and the textarea appear .How can i restrict it .
$scope.editorEnabled = false;
$scope.enableEditor = function() {
$scope.editorEnabled = true;
};
<div ng-repeat="(key,rec) in recordcomment">
<div class="row">
<div class="col-md-10">
<div class="panel panel-default">
<div class="panel-heading">
heading
</div>
<div class="panel-body" style="background-color:white;">
<p ng-hide="editorEnabled">{{rec.comment}}</p>
<textarea ng-model="rec.comment" ng-show="editorEnabled"></textarea>
<button class="btn btn-primary pull-right" ng-click="enableEditor()">Edit</button>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body" style="background-color:white;">
<p ng-hide="rec.editorEnabled">{{rec.comment}}</p>
<textarea ng-model="rec.comment" ng-show="rec.editorEnabled"></textarea>
<button class="btn btn-primary pull-right" ng-click="enableEditor(rec)">Edit</button>
</div>
$scope.enableEditor = function(context) {
context.editorEnabled = true;
};
Use rec instead of this
Because this means current context of ng-repeat directive..
So to make it effective we need to modify the object...
Hence we need to pass it as i have use rec in function param
Try this in case do comment
Add the editorEnabled object with ng-rpeat object. so it will be consider with the array object. and you can pass this current object via click function() and set true/false the editorEnabled object.
Code looks like.
<div class="panel-body" style="background-color:white;">
<p ng-hide="rec.editorEnabled">{{rec.comment}}</p>
<textarea ng-model="rec.comment" ng-show="rec.editorEnabled"></textarea>
<button class="btn btn-primary pull-right" ng-click="enableEditor(this)">Edit</button>
</div>
$scope.enableEditor = function(context) {
context.editorEnabled = true;
};

x-editable nested editable-select not submitting

I have a editable-select nested inside other, when I submit the nested editable-select changes, it does not call the onaftersave assigned function ('vm.addOperation()'), it also shows the outter editable-select edit form.
I want it just to show the nested edit form and the function call to work.
My html code:
<div editable-select="vm.selectedUser"
e-ng-options="user.objectId as user.displayName for user in vm.users"
onshow="vm.getUsers()"
onaftersave="vm.addUser()">
<div class="container" ng-repeat="u in entity.authorizedUsers">
<div class="row">
<div class="col-xs-2">
{{u.id}}
</div>
<div class="col-xs-4">
<div editable-select="vm.selectedOperation"
e-ng-options="operation.id as operation.name for operation in vm.operations"
onshow="vm.getOperations()"
onaftersave="vm.addOperation()">
<div class="container" ng-repeat="op in u.authorizedOperations">
<div class="row">
<div class="col-xs-3">
{{op.name}}
</div>
<div class="col-xs-push-2">
<button class="btn btn-xs btn-danger"
ng-click="vm.removeOperation(entity.id, u.id, op.id)">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-push-4">
<button class="btn btn-xs btn-warning pull-left"
ng-click="vm.removeuser(entity.id, u.id)">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
</div>
</div>
I've manage to fix the problem with the following code. It's an ugly workaround tho, please if someone has a more elegant solution I'd very much appreciate it.
in html:
<div editable-select="vm.selectedOperation"
e-form ="nestedForm"
onshow="vm.getOperations()"
ng-click="nestedForm.$show(); vm.xEditableNestedFormFix(nestedForm); $event.stopPropagation()"
e-ng-options="operation.id as operation.name for operation in vm.operations"
onaftersave="vm.addOperation()">
in js:
vm.xEditableNestedFormFix = function (form) {
var editorElement = form.$editables[0].controlsEl[0].firstChild;
editorElement.onclick = function (event) {
event.stopPropagation();
}
var submitButton = form.$editables[0].buttonsEl[0].firstChild
submitButton.onclick = function (event) {
form.$submit();
event.stopPropagation();
}
var cancelButton = form.$editables[0].buttonsEl[0].lastChild
cancelButton.onclick = function (event) {
event.stopPropagation();
}
}

How do I set the ui.bootstrap collapse feature to collapsed on page load?

I'm using ui.bootstrap and I'm trying to use the collapse function.
In my code what's happening is the default state is expanded, when the load weather button is clicked the div is collapsed and after the data has been loaded it expands.
What do I need to do to my code to get it to have a collapsed state on page load and only expand/contract when the button has been clicked?
Here's my code:
<div ng-controller="weatherCtrl">
<div>
<button ng-model="hotel" class="btn btn-default"
ng-click="loadWeather(hotel); isCollapsed = !isCollapsed">load weather</button>
<hr>
<div collapse="isCollapsed">
<div class="well well-lg">Some content</div>
</div>
</div>
</div>
.controller('weatherCtrl', function ($scope, weather) {
$scope.loadWeather = function (hotel) {
console.log('loadWeather')
console.log('hotel')
console.log(hotel)
weather.get({}, function (data) {
console.log('data')
console.log(data)
$scope.isCollapsed = false;
})
}
})
I got it working by using ng-init on a parent element:
<div ng-controller="weatherCtrl" ng-init="isCollapsed = !isCollapsed">
<div>
<button ng-model="hotel" class="btn btn-default"
ng-click="loadWeather(hotel)">load weather</button>
<hr>
<div collapse="isCollapsed">
<div class="well well-lg">Some content</div>
</div>
</div>
</div>

ng-click not executing controller function

I have a very simple function in one of my angular controllers
$scope.search = function () {
alert("Search");
};
and from my view I have
<button type="button" data-ng-click="search()"><i class="fa fa-search"></i></button>
The function is never executed when the button is clicked, but the rest of the code in my controller is executed as expected. Is there any reason why the ng-click directive will not fire my function?
I have similar controllers all working as expected.
Update
The button is within a bootstrap 3 modal, when the button is moved out of the modal, the click event works. Any reason for this happening?
Update
The button is within scope of the controller, here is my controller and view for clarity
(function () {
var module = angular.module("crest");
var brokerGridController = function ($scope, readEndpoint, readBroker) {
$scope.endpoint = "";
$scope.isBusy = false;
$scope.havebroker = false;
$scope.brokers = [];
$scope.searchCriteria = "";
$scope.exception = "";
var setEndpoint = function (response) {
$scope.endpoint = response.Endpoint;
};
readEndpoint.read("BusinessLogicAPI").then(setEndpoint);
var onSuccess = function (response) {
if (response.Message.MessageType == 1) {
onError();
}
$scope.havebrokers = response.brokers.length > 0;
angular.copy(response.brokers, $scope.brokers);
angular.copy(response.Message.body, $scope.exception);
};
var onError = function () {
$("#errorMessageModal").modal("show");
};
$scope.search = function () {
alert("Search");
};
};
module.controller("brokerGridController", ["$scope", "readEndpoint", "readBroker", brokerGridController]);
}());
and the view
<div data-ng-controller="brokerGridController">
<div>
<div class="col-md-4">
<div class="contacts">
<div class="form-group multiple-form-group input-group">
<div id="searchBrokerDropdown" class="input-group-btn input-group-select">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="concept">Broker Name</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Broker Name</li>
</ul>
<input type="hidden" class="input-group-select-val" name="contacts['type'][]" value="phone">
</div>
<input type="text" name="contacts['value'][]" class="form-control" data-ng-model="searchPhrase">
<span class="input-group-btn searchButton">
<button type="button" class="btn btn-success btn-add" data-ng-click="$parent.search()"><i class="fa fa-search"></i></button>
</span>
</div>
</div>
</div>
</div>
<div>
<div class="col-md-12">
#Html.Partial("_Loading", new LoadingViewModel() { DisplayText = "Loading brokers..." })
<div data-ng-show="!isBusy && !haveBrokers">
<h3>No brokers found.</h3>
</div>
<div class="panel" data-ng-show="!isBusy && haveBrokers">
<div class="panel-heading">
<h4 class="panel-title">Brokers</h4>
<div class="pull-right">
<span class="clickable filter" data-toggle="tooltip" title="Filter Brokers" data-container="body">
<i class="fa fa-filter"></i>
</span>
</div>
</div>
<div class="panel-body">
<input type="text" class="form-control" id="task-table-filter" data-action="filter" data-filters="#task-table" placeholder="Filter Tasks" />
</div>
<table class="table table-hover" id="task-table">
<thead>
<tr>
<th>Broker Name</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="broker in brokers">
<td>{{ broker.Name }}</td>
<td data-ng-show="searchCriteria != 'PolicyNumberLike'"><i class="fa fa-search"></i> View Policies</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
You have to check 2 things in that situation:
Check if your button is in the front (rise his z-index or check is :hover is working), maybe it is not on top so it can't be clickable.
Check if that buttont dont have own $scope (it is crated in subdirective, or in ng-repeat for example), in taht situation check:
<button type="button" data-ng-click="$parent.search()"><i class="fa fa-search"></i></button>
If that 2 things dosen't work check if any command ex. console.log('test_mode') will fire after click.
It's most likely that the button is outside of controller scope, if you provide model with a specific controller you should put search function inside said controller, if you want to keep it in parent controller specify it like this:
$scope.modalFunctions = {
search: function () {
//do something
}
}
then use ng-click="modalFunctions.search"
Ok, I finally found the problem. My angular view is within a bootstrap wizard component (within a bootstrap modal) that I copied from Bootsnipp. The problem was with the javascript that was supplied,
wizardContent.html(currStep.html());
this piece of code replaced the wizard content with the HTML of the correct step. I modified the javascript to hide and show the correct steps instead of copying the HTML of the correct step to the div displayed to the user, which resolved the issue.

access angular cookie in view

I fill my angularjs cookie with some objects like
$scope.benchmarks = function(product) {
$cookieStore.put("benchmark_prods", product);
$scope.benchmarks = $cookieStore.get("benchmark_prods");
console.log(benchmarks); //is getting filled
};
than I would like to access in view if cookies contains elements but I don't know how
I tried
<div ng-repeat="product in products">
//here the click event which is stroing product in cookie an simultanly shuld update cookie loop
<a data-placement="bottom" ng-click='benchmarks(product)' title="" rel="tooltip" class="button-icon jarviswidget-delete-btn" href="javascript:void(0);" data-original-title="Delete"><i class="fa fa-bookmark"></i></a>
</div>
<div ng-controller="MainCtrl">
<fieldset>
<section>
<div class="panel-heading">
<legend class="params">
<h4 class="panel-title">
Benchmarks
</h4>
</legend>
</div>
<div ng-repeat="benchmark_prod in benchmarks">
{{benchmark_prod}}
</div>
<div class="inline-group" id="conf_display">
</div>
</div>
but doesn’t work
$scope.benchmarks = function(product)
{
$cookieStore.put("benchmark_prods", product);
if($cookieStore.get("benchmark_prods")!=null && $cookieStore.get("benchmark_prods")!="")
{
$scope.benchmarkspro=$cookieStore.get("benchmark_prods")
}
console.log(benchmarkspro); //is getting filled
};
change benchmarks to benchmarkspro in html.

Resources