can I assign multiple $watchCollection programmaticaly? - angularjs

Imagine that I have an array called buckets. that array will contain objects called bucket where each bucket has a property called images which is an array. Example:
vm.buckets = [
{name: "bucket1", images: []},
{name: "bucket2", images: []},
{name: "bucket3", images: []}
]
I am dynamically adding new buckets to vm.buckets , but also dynamically adding new images to each bucket. Is there a way to create a new $watchCollection and assign it to every new bucket so that i can watch for new images being inserted into each bucket?

angular.module('app', []).controller('ctrl', function($scope) {
var vm = this;
vm.buckets = [
{ name: "bucket1", images: [] },
{ name: "bucket2", images: [] },
{ name: "bucket3", images: [] }
];
var counter = vm.buckets.length;
vm.Addbucket = function() {
var temp = {
name: 'bucket' + (++counter),
images: []
};
vm.buckets.push(temp);
AddWatch(temp);
}
vm.DeleteLastBucket = function(){
vm.buckets[vm.buckets.length - 1].unregisterWatch();
vm.buckets.splice(vm.buckets.length - 1, 1);
}
function AddWatch(x) {
var index = vm.buckets.indexOf(x);
var id = `buckets[${index}].images`;
x.unregisterWatch = $scope.$watchCollection(id, function() {
console.log(`Changes at ${x.name} images`);
});
}
$scope.buckets = vm.buckets;
vm.buckets.forEach(AddWatch);
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<div ng-app='app' ng-controller='ctrl as vm'>
<ul>
<li ng-repeat='item in vm.buckets'>
{{item.name}}: {{item.images.length}} images
<button ng-click='item.images.push("temp")'>Add image</button>
</li>
</ul>
<button ng-click='vm.Addbucket()'>Add bucket</button>
<button ng-click='vm.DeleteLastBucket()'>Delete last bucket</button>
</div>

Related

How to populate the values in a response object array data using *ngFor in Angular

I want to display data coming from a backend Api in Angular using *ngFor.But data is coming as an object which contains an array of size 10.This the image of the backend response that shows in console.log(hotels);
This is the angular code which i have written in component.ts file
hotelInfo = [];
hotelInfo2 = [];
getTopHotelInfo() {
const params = [];
params.push({code: 'dateType', name: 'CHECKIN'});
params.push({code: 'fromDate', name: '2018-01-01'});
params.push({code: 'toDate', name: '2019-01-01'});
params.push({code: 'topN', name: 10});
this.dashboardServiceHandler.getTopHotelInfo([], params).subscribe(
hotels => {
console.log(hotels);
this.hotelInfo.push(hotels);
console.log(this.hotelInfo);
for (let i = 0; i < this.hotelInfo.length; i++) {
const hotel = this.hotelInfo[i];
console.log(hotel);
/// this.hotelInfo2.push(hotels[i]);
this.hotelInfo2.push({code: hotel.code, name: hotel.name});
console.log(this.hotelInfo2[i]);
}
});
}
This is the code which i have written in component.html file
<li *ngFor="let hotel of hotelInfo">
<div class="c-inbox-widget__item">
<div class="c-inbox-widget__item__avatar" style="background: #A3A1FB">
01
</div>
<div>
<span class="c-inbox-widget__item__author">{{hotel.name}}</span>
<!--<span class="c-inbox-widget__item__text">Canada</span>-->
</div>
<div class="c-inbox-widget__item__value">$29,193</div>
</div>
</li>
How could I get those data as an array to *ngFor
Try this way. your response is an object and it contains an array with key responseObj.
getTopHotelInfo() {
const params = [];
params.push({code: 'dateType', name: 'CHECKIN'});
params.push({code: 'fromDate', name: '2018-01-01'});
params.push({code: 'toDate', name: '2019-01-01'});
params.push({code: 'topN', name: 10});
this.dashboardServiceHandler.getTopHotelInfo([], params).subscribe(
hotels => {
console.log(hotels);
this.hotelInfo = hotels.responseObj;
});
}
Now run ngFor on hotelInfo. It should work as per your response.
Example:
let obj = {
responseObj: [
{ name: 'a' },
{ name: 'b' },
{ name: 'c' }
]
};
console.log(obj.responseObj);
You could use keyValue pipe in angular
<div *ngFor="let hotel of hotelInfo">
<div *bgFor="let q of hotel | keyvalue>
{{q.key}} - {{q.value}}
</div>
</div>

How to display repeated drop down based on button selection in AngularJS

I need to display a drop down along with Plus button at first time. Based on button click it should display one more combination , I mean same drop down with options excluded previous selected value which we have from the first drop down and the plus button. This action should be repeat based on plus button selection.
Here is my code:
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.init = function() {
$scope.display = false;
};
$scope.init();
$scope.records = [
{ id: "part1", part: "Frt Bumper Cover" },
{ id: "part2", part: "Frt Lwr Bumper Cover" },
{ id: "part3", part: "Frt Upr Bumper Cover" },
{ id: "part4", part: "Hood Panel" },
];
$scope.changedValue = function(key) {
// alert(key);
//var index = $scope.records.indexOf(item);
//alert(index);
$scope.records.splice(index, 1);
//delete $scope.records[key];
// alert(JSON.stringify($scope.records));
};
$scope.sample = function() {
$scope.display = true;
// alert("sample: "+$scope.display);
//alert("inside sample:::"+JSON.stringify($scope.records));
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl" ng-init="init()">
<div>
<select ng-model="selectedRecord"
ng-change="changedValue(selectedRecord)"
ng-options="record.id as record.part for record in records">
<option ng-repeat="x in records">{{x.part}}</option>
</select>
<input type="submit" value="+" ng-show="records.length!=1"
ng-click="sample()" />
</div>
<div ng-show="display">
<select ng-model="selectedRecord"
ng-change="changedValue(selectedRecord)"
ng-options="record.id as record.part for record in records">
</select>
<input type="submit" value="+" ng-show="records.length!=1"
ng-click="sample()" />
</div>
</body>
I am unable to display like that, please share your ideas to do this
My friend, i think i have a solution for your problem. :D
Its very basic code i think, so i would be happy to explain more in depth if needed.
look code here: plnkr, this is basically all the code, so its my first plunker.
$scope.originalRecords = [
{ id: "part1", part: "Frt Bumper Cover" },
{ id: "part2", part: "Frt Lwr Bumper Cover" },
{ id: "part3", part: "Frt Upr Bumper Cover" },
{ id: "part4", part: "Hood Panel" },
];
$scope.selectArray = [{selectedOption: null, options: $scope.originalRecords}];
$scope.selectedOption =[];
$scope.hideButton = false;
$scope.addNewSelect = function (arrayToSearch, selectedOption) {
var index = arrayToSearch.map(function(d) { return d['part'];}).indexOf(selectedOption);
var newRecords = arrayToSearch.slice();
newRecords.splice(index, 1);
if (newRecords.length > 0) {
$scope.selectArray.push({selectedOption: null, options: newRecords});
} else {
$scope.hideButton = true;
}
}
Hope it helps.

VueJs2:remove item from parent array in component

I have a component with prop List. List is list of input files. At once input changed I add another one input.
Weird behavior if I try to delete .
https://jsfiddle.net/apokjqxx/115/
removeAnother: function(item) {
var vm = this;
var num = vm.$parent.cornerList.indexOf(item);
vm.$parent.cornerList.splice(num, 1);
},
How to reproduce:
choose file in first input
choose file in second input (will added after step 1)
choose file in third input (will added after step 2)
then click to remove on first item in list
Expected: removed first item but has removed last added
Use a key on your list.
<div v-for="(item, index) in list" :key="item.id">
I modified your fiddle to generate an id for each object added to the cornerList array.
var formuploadimage = Vue.extend({
template: '#template-form-upload-image',
props: {
list: {
type: Array
}
},
data: function() {
return {
isFileChanged: false
}
},
watch: {
validCnt: function() {
},
},
methods: {
onFileChange: function(item) {
var vm = this;
let id = Math.max.apply(Math, vm.$parent.cornerList.map(c => c.id)) + 1
var newItem = {id};
vm.$parent.cornerList.push(newItem);
},
removeAnother: function(item) {
var vm = this;
var num = vm.$parent.cornerList.indexOf(item);
vm.$parent.cornerList.splice(num, 1);
},
},
});
var app = new Vue({
el: ".lists-wrappers",
data: {
cornerList: [{id: 1}],
},
components: {
formuploadimage: formuploadimage
},
methods: {
},
});
.select-file{
width:250px;
border:1px solid red;
}
<script src="https://unpkg.com/vue#2.4.4/dist/vue.js"></script>
<div class="lists-wrappers">
<formuploadimage :list="cornerList"></formuploadimage>
</div>
<script type="text/x-template" id="template-form-upload-image">
<div>
<div v-for="(item, index) in list" :key="item.id">
<div class="select-file">
REMOVE<br/>
<label for="file-input">
+Add photo
</label>
<input type="file" #change="onFileChange(item)" />
</div>
</div>
</div>
</script>

How to use the value in ngRepeat as a dynamic way to access a scope?

I have a set of value that I would like to dynamically generate in my view. How can I go about doing it in the following way?
$scope.mainKeyMapping = [
{
name: 'category1',
otherThings: ''
},
{
name: 'category2',
otherThings: ''
},
{
name: 'category3',
otherThings: ''
},
{
name: 'category4',
otherThings: ''
},
{
name: 'category5',
otherThings: ''
}
];
$scope.category1 = {something....}
$scope.category2 = {something....}
$scope.category3 = {something....}
$scope.category4 = {something....}
$scope.category5 = {something....}
HTML
<div ng-repeat="cat in mainKeyMapping">
{{category1}} // outputs obj
{{cat.name}} // outputs string "category1" <----- how do I output the obj?
</div>
First, put your categories into a collection:
$scope.categories = {
category1: {something....},
category2: {something....}
};
Now simply access the right category in your html:
<div ng-repeat="cat in mainKeyMapping">
{{categories.category1}} // outputs obj
{{categories[cat.name]}} // outputs obj
</div>

KendoGrid/Angular: cannot create grid columns/data dynamically

In this plunk I have an empty grid (without columns). When I click on "Build Grid" I need to add columns (taken from an array) and also add a row to the table.
The problem is that the columns are not added to the grid, any ideas? If I try to refresh the grid, I get an undefined error.
HTML:
<button ng-click="buildGrid()">Build Grid</button>
<div kendo-grid="grid" k-options="gridOptions" k-data-source="ds"></div>
Javascript:
var app = angular.module("app", [ "kendo.directives" ]);
function MyCtrl($scope) {
$scope.ds = []
$scope.colsList = [{ name: "col1" },
{ name: "col2" },
{ name: "col3" },
{ name: "col4" }];
var gridCols = [];
$scope.gridOptions = {
columns: gridCols
};
$scope.buildGrid = function() {
$scope.data = {};
for (var x=0;x<$scope.colsList.length;x++) {
var col = {};
col.field = $scope.colsList[x].name;
col.title = $scope.colsList[x].name;
$scope.data[col.field] = "" + (1111 * (x+1));
gridCols.push(col);
}
// add one row to the table
$scope.ds.push($scope.data);
//$scope.grid.refresh();
};
}
You need to use k-rebind so that the grid reinitializes (you can't set the columns dynamically on an existing grid):
<div kendo-grid="grid"
k-options="gridOptions"
k-data-source="ds"
k-rebind="gridOptions"></div>
(demo)

Resources