Add data in List onclick event - javascript

I am trying to add items from textbox into the list and want to display on main page. Here is my code sample
HTML Code:
<div ng-controller="purchaseInvoiceInquiryController as c" ng-init="c.initializeController()">
<input type="text" ng-model="c.name" placeholder="Enter the Book" />
<input type="text" ng-model="c.price" placeholder="Enter a Price" />
<button ng-click="c.addBooks()">Add the Book</button></p>
<td ng-repeat="x in c.books"> {{ x.name + ' - ' + x.price}}</td>
and angular controller code is :
this.addBooks = function () {
c.books = [{
name: c.name,
price: c.price
}];
};
Its only add one item in that list when i try to add another item it will override the values.

Initialize books to empty array in controller and use push method of array to add new books. You may need to add logic to avoid duplicates.
this.books = [];
this.addBooks = function () {
this.books.push({
name: c.name,
price: c.price
});
};

Use push instead.
this.addBooks = function () {
c.books.push({
name: c.name,
price: c.price
});
};

Related

Managing a Reactive Form value and the value is an object

I have an Array I'm getting from the server, which contains Objects like this:
[
{LanguageName: 'English', ID : 2},
{LanguageName: 'Dutch', ID : 1},
{LanguageName: 'portuguese', ID: 3},
]
I'm handling this by by creating a Form-Array.
My Issue:
I want that if the user changes this input, it will change only the property of the Name, something like: anyFormName.controls.value.LanguageName, and not replacing the whole value altogether to a string, so insted of end up getting :
anyFormName.controls.value = "User's Input"
, I'll get:
anyFormName.controls.value = {LanguageName: "User's Input", ID : 2}
I've worked around this issue before with setValue() to the specific control, and saving the data in another array so I can compare the position by the indexes of the form Array. seems to me there probably be a better way...
thanks a lot!
Tal, in general you'll get a formArray like
<div *ngIf="myFormArray" [formGroup]="myFormArray">
<div *ngFor="let item of myFormArray.controls; let i=index" [formGroupName]="i">
<input formControlName="ID">
<input formControlName="LanguageName">
</div>
</div>
{{myFormArray?.value|json}}
//Or
<div *ngIf="myForm" [formGroup]="myForm">
<div formArrayName="data">
<div *ngFor="let item of myForm.get('data').controls; let i=index" [formGroupName]="i">
<input formControlName="ID">
<input formControlName="LanguageName">
</div>
</div>
</div>
{{myForm?.value|json}}
where you has some like
myForm:FormGroup
myFormArray:FormArray;
values=[
{LanguageName: 'English', ID : 2},
{LanguageName: 'Dutch', ID : 1},
{LanguageName: 'portuguese', ID: 3},
]
ngOnInit() {
this.myForm=this.fb.group({
data:this.fb.array(this.createFormArray(this.values))
})
this.myFormArray=this.fb.array(this.createFormArray(this.values));
}
createFormArray(values:any):FormGroup[]
{
return values.map(x=>{
return this.fb.group(
{
LanguageName:x.LanguageName,
ID:x.ID
}
)
})
}
Just not include the input formControlName="ID"
As long as I understand you properly, you're trying to change the form control name instead of its value. That can be accomplished by this method:
changeFormFieldName(oldField: string, newField: string): void {
var newControls: {[key: string]: FormControl} = {};
Object.keys(this.form.controls).map((field: string) => {
if (field==oldField) {
newControls[newField] = this.form.controls[field];
} else {
newControls[field] = this.form.controls[field];
}
});
this.form = new FormGroup(newControls);
}
assuming your form group object is under this.form.

AngularJS - Checklist-Model doesn't update the model correctly on checkbox change

I'm new to AngularJS and I'm having a problem with the Checklist-Model directive.
I'm using one of their examples to replicate this behavior.
When I click one checkbox and call a function, the model seems to be updated
correctly and is shown accordingly on the template, but when I log the contents of the model on the console the value of the checkbox I clicked is missing.
Here's when the strange stuff starts. If I click the checkbox again, then the value is removed from the template but I can see it on the console.
Here's the code:
HTML:
<div ng-controller="DemoCtrl">
<label ng-repeat="role in roles">
<input type="checkbox" checklist-model="user.roles"
checklist-value="role.text"
ng-change="changeValues(role)"> {{role.text}}
</label>
<br>
<button ng-click="checkAll()">check all</button>
<button ng-click="uncheckAll()">uncheck all</button>
<button ng-click="checkFirst()">check first</button>
<br><br>
user.roles {{ user.roles | json }}
</div>
Angular:
angular.module("DemoApp", ["checklist-model"])
.controller('DemoCtrl', function($scope) {
$scope.roles = [
{id: 1, text: 'guest'},
{id: 2, text: 'user'},
{id: 3, text: 'customer'},
{id: 4, text: 'admin'}
];
$scope.user = {
roles: ['guest', 'admin']
};
$scope.checkAll = function() {
$scope.user.roles = $scope.roles.map(function(item) { return item.id; });
};
$scope.uncheckAll = function() {
$scope.user.roles = [];
};
$scope.checkFirst = function() {
$scope.user.roles.splice(0, $scope.user.roles.length);
$scope.user.roles.push(1);
};
$scope.changeValues = function() {
console.log('Roles: ', JSON.stringify($scope.user.roles));
}
});
The first time I click a checkbox i.e: 'User' the output on the console is:
Roles: ["guest","admin"]
Then, when I uncheck the same checkbox the output is:
Roles: ["guest","admin","user"]
In the application I'm developing I MUST call a function when the checkbox changes it's value that's why I using the "ng-change" directive.
Can anybody explain what I'm doing wrong?
Thanks in advance.
checklist-model it's used the Id as checklist-value in the checkbox and in your code you use the text.
So in the function $scope.checkAll you should return the item.text instead item.id and in the function $scope.checkFirst you should push the $scope.roles.find(item => item.id == 1).text
And the rest seems correct

Search Filtering with Vue2

<!-- Facets in the v-for below is an array of objects, each element (facet) in the
facets array has a property which is an array of facetItems. -->
<div class="row" v-for="(facet, facetsIndex) in facets" :key="facetsIndex">
<!-- Since we are inside the v-for, it creates a search input for each facet.
Each facet search input will only search for facetItems belonging to that facet.
We know which facet to search in because we pass the facetIndex to the searchFilter function. -->
<input type="text" #keyup="searchFilter(facetsIndex)">
<div v-if="facet.facetItems.length > 0">
<div class="facet-header">{{config[core.toLowerCase()].displayNames[facet.facetName]}}</div>
<div class="row facet-scroll" >
<!-- The v-for below is used to iterate over the facetItems for each facet. displayFacetItems() is called
for each array of facetItems corresponding to each facet on initial render. displayFacetItems() is also called
on each keyup event emitting from the corresponding facet search input. displayFacetItems() should return an
array of facetItems objects, and when a search input is entered, it should return a filtererd array of facetItems
based on the search results. -->
<div class="facet-item" v-for="(item, facetItemIndex) in displayFacetItems(facetsIndex)" :key="facetItemIndex">
<facet v-bind:item="item" v-bind:facet="facet"></facet>
</div>
</div>
<hr class="divider"/>
</div>
</div>
methods: {
searchFilter (facetsIndex) {
let searchTerm = event.currentTarget.value
this.displayFacetItems(facetsIndex, searchTerm)
},
displayFacetItems (facetsIndex, searchTerm) {
if (!searchTerm) return this.facets[facetsIndex].facetItems
return this.facets[facetsIndex].facetItems.filter((facetItem) => {
return _.includes(facetItem.name.toLowerCase(), searchTerm.toLowerCase())
})
}
},
Please see the comments in the code above for an explanation of what's happening in my code.
I don't understand why my code above isn't working. I'm trying to implement search functionality for each facet. When searching, the filtering should only happen for facetItems belonging to that specific facet.
I've been able to verify that displayFacetItems does return an array of filtered facetItems but for some reason the filtered array isn't updated in the DOM.
This might have something to do with Vue's data binding or the process in which Vue updates the DOM. Any pointers on what I'm doing wrong is greatly appreciated.
My code took inspiration from this article:
https://nickescobedo.com/1018/introduction-to-vue-js-filtering-with-lodash
You can see my jsfiddle for search items on Vuejs. I hope this will help you.
<div id="app">
<label>
Search name: <input type="text" v-model='searchString'>
</label> <br>
<transition-group tag='ul' name='my-list'>
<li v-for='item in filteredList' :key='item.id' class="my-list-item">
{{item.name}}
</li>
</transition-group>
</div>
<script>
const app = new Vue({
el: '#app',
beforeMount() {
const req = fetch('https://jsonplaceholder.typicode.com/users');
req.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('Bad request: ' + response.status);
})
.then(users => {
this.users = users;
this.nextId = this.users.length + 1;
});
},
data: {
searchString: '',
users: [
{id: 1, name: 'Alex'},
{id: 2, name: 'Bob'},
{id: 3, name: 'Sandy'},
],
},
computed: {
filteredList: function() {
const searchString = this.searchString.toLowerCase();
return this.users.filter(item => item.name.toLowerCase().includes(searchString));
}
}
});
</script>
The param facetsIndex is not reactive, please take a look at your jsconsole, you should have a warning about this and not only this, your code logic is totally wrong.
You could use a v-model on input,
create a filteredFacets property,
use this property in your loop.
Just an example, you should read more about how VueJS works :
https://v2.vuejs.org/v2/guide/

reset ng-model from controller in ng-repeat

I am trying to create a list of editable inputs from a list of items. I want the user to be able to edit any of the items, but if they change there mind they can click a button and reset it back to the way it was.
So far I have everything working except the reset.
my html
<div ng-app ng-controller="TestController">
<div ng-repeat="item in list">
<label>Input {{$index+1}}:</label>
<input ng-model="item.value" type="text" ng-click="copy(item)"/>
<button ng-click="reset(item)">
x
</button>
</div>
{{list}}<br>
{{selected_item_backup}}
</div>
my controller
function TestController($scope) {
$scope.selected_item_backup = {};
$scope.list = [ { value: 'value 1' }, { value: 'value 2' }, { value: 'value 3' } ];
$scope.reset = function (item) {
// i know this wont work for many reasons, it is just an example of what I would like to do
item = $scope.selected_item_backup;
};
$scope.copy = function (item) {
angular.copy(item, $scope.selected_item_backup);
};
}
and here is a fiddle
http://jsfiddle.net/ryanmc/1ab24o4t/1/
Keep in mind that this is a simplified version of my real code. My objects will have many editable fields each. Also they are not indexed, and so the index cannot be relied on. I just want to be able to assign the original item on top of the new and have it replaced.
This is work solution jsfiddle
function TestController($scope) {
$scope.list = [{
value: 'value 1'
}, {
value: 'value 2'
}, {
value: 'value 3'
}];
var orgiinalList = [];
angular.forEach($scope.list, function(item) {
orgiinalList.push(angular.copy(item));
});
$scope.reset = function(index) {
$scope.list[index] = angular.copy(orgiinalList[index]);
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="TestController">
<div ng-repeat="item in list">
<label>Input {{$index+1}}:</label>
<input ng-model="item.value" type="text" />
<button ng-click="reset($index)">
x
</button>
</div>
{{list}}
<br>
</div>
Changing your reset function so that it looks like this:
$scope.reset = function(index) {
$scope.list[index].value = "value "+ (index+1);
};
will make it so that your 'reset' buttons restore what would be those original values...
Angular controller:
function TestController($scope) {
$scope.selected_item_backup = {};
$scope.list = [{
value: 'value 1'
}, {
value: 'value 2'
}, {
value: 'value 3'
}];
$scope.reset = function(index) {
$scope.list[index].value = "value " + (index+1);
};
$scope.copy = function(item) {
angular.copy(item, $scope.selected_item_backup);
};
}
HTML:
<div ng-app ng-controller="TestController">
<div ng-repeat="item in list">
<label>Input {{$index+1}}:</label>
<input ng-model="item.value" type="text" ng-click="copy(item)" />
<button ng-click="reset($index)">
x
</button>
</div>
</div>
The values of your array are directly modeled by those inputs - therefore as a user types changes into those inputs they are directly manipulating the $scope.list array so you cant really use it as a reference... Hope that makes sense.
You can't use global functions as controllers in newer versions of angular but you can register your controllers in your application:
<div ng-app ng-controller="TestController">
<div ng-repeat="item in list">
<label>Input {{$index+1}}:</label>
<input ng-model="item.value" type="text" ng-click="copy($index,item)"/>
<button ng-click="reset($index,item)">
x
</button>
</div>
{{list}}<br>
{{selected_item_backup}}
function TestController($scope) {
$scope.selected_item_backup = [];
$scope.list = [ { value: 'value 1' }, { value: 'value 2' }, { value: 'value 3' } ];
$scope.reset = function (index) {
$scope.list[index].value = $scope.selected_item_backup[index];
};
$scope.copy = function (index,item) {
// backup the old value
$scope.selected_item_backup[index] = item.value;
};
}

update scope object with filter - AngularJS

I need to update assign filtered objects from $scope.Departments to $scope.FilteredDepartments on change text field.
HTML:
<input type="text" ng-change="searchItems(searchquery)" ng-model="searchquery">
AngularCode:
$scope.Departments= [{id: 1, name:'ABC'},{id: 2, name:'XYZ'}...];
$scope.searchItems = function (searchString) {
//Need to do something here
}
How do I filter with name and assign filtered result to $scope.FilteredDepartments ?
Thanks for help
HTML:
<input type="text" ng-model="searchValue">
<h3>Filter Ones</h3>
<div ng-repeat="department in filteredDepartments">
<p>{{department.name}}</p>
</div>
JS:
$scope.departments= [{id: 1, name:'ABC'},{id: 2, name:'XYZ'}];
$scope.$watch(function () {
return $scope.searchValue;
}, function () {
$scope.filteredDepartments = $filter('filter')($scope.departments, $scope.searchValue);
});
don't forget to inject $filter into the controller

Categories