RivetsJS - Dynamically bind an input to a list item - javascript

I'm using RivetsJS to create a dynamic list which will be editable via an input box, and use the two-way data binding to update the element...
The list code is:
<ul id="todo">
<li rv-each-todo="list.todos">
<input type="checkbox" rv-idx="todo.idx" rv-checked="todo.done">
<span>{ todo.summary }</span>
</li>
<ul>
And the RivetsJS binding:
<script type="text/javascript">
var list = {
"todos": [
{"idx":133, "done":1,"summary":"Eat"},
{"idx":25, "done":0,"summary":"Code"},
{"idx":33, "done":1,"summary":"Sleep"},
{"idx":24, "done":0,"summary":"Repeat"}
]
}
rivets.bind($('#todo'), {list: list})
</script>
Now I want to create an element which can edit the items in the list in real time.. something like
<input rv-editing-idx="133"></input>
So that when I change the input data, element 133 on the list would change.. if I change the rv-editing-idx="133" attribute on the input, then another element would be edited..
Any ideas on how I can acheive that?

I hope you figured it out by yourself, if not, here's a possible solution: https://jsfiddle.net/nohvtLhs/1/
You can bind the input element, with the selected element from the array.
How you select the element of the array its up to you, i used in the example some radio input elements. After that, you have a simple binding, like you do it usually.
HTML:
<ul id="todo">
<li rv-each-todo="list.todos">
<input type="radio" rv-idx="todo.idx" rv-checked="todo.done" name="todo" rv-on-change="list.change">
<span>{ todo.summary }</span>
</li>
<ul>
<input id="changeele" rv-value="summary"></input>
JS:
var ele = document.getElementById('changeele');
var eleBinding = rivets.bind(ele, {});
var list = {
"todos": [
{"idx":133, "done":true,"summary":"Eat"},
{"idx":25, "done":false,"summary":"Code"},
{"idx":33, "done":false,"summary":"Sleep"},
{"idx":24, "done":false,"summary":"Repeat"}
],
"change": function(event, scope) {
eleBinding.unbind();
eleBinding = rivets.bind(ele, scope.list.todos[scope.index]);
}
}
rivets.bind(document.getElementById('todo'), {list: list})

Related

How to add `<input>` elements with button click AngularJS

How to use ng-bind in realtime after appending an object
I want to be able to add a new element and use the ng-bind property to change the value of the new element.
I've tried multiple things, please see the code below for the best I've been able to come up with.
$(document).ready(function() {
$("#create-input").click(function() {
var newInput = document.createElement("p");
var code = document.createElement("span");
code.innerHTML = "{{input2}}";
newInput.innerHTML = "<p>{input2}: <input type='text' ng-model='name2'>  {{name2}}</p>";
$("#target-container").append(newInput);
$("#main-container").append(code);
});
});
When I add text the newly appended input, the appended {{name2}} value does not change. I do not understand why I am unable to change {{name2}} via the text input box after appending.
Use the ng-repeat directive to add input elements to the DOM:
angular.module("app",[])
.controller("ctrl",function($scope) {
$scope.arr=[
{name: "name1", value: ""}
];
$scope.addInput = function() {
$scope.arr.push( {
name: "name" + ($scope.arr.length+1),
value: ""
})
};
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl" >
<div ng-repeat="elem in arr">
{{elem.name}}:
<input ng-model="elem.value">
</div>
<button ng-click="addInput()">Add Input</button>
<div>{{arr}}</div>
</body>

Hide other elements in list

I have the below code:
<li *ngFor="let item of Array let i = index">
<span>
<label (dblclick)="editTag($event,i)">
{{item.tag}}
</label>
<input type="text" #tagInput />
</span>
</li>
The code is in a for loop. When I click on a label, all labels should be hidden and the input should be visible. Currently, when I click on each label, the other remain open. How do I hide the other span when clicking on any item?
I have below code in .ts
#ViewChild('tagInput') tagNameTextInput: ElementRef;
editTag(event: any,index: any) {
//console.info(event);
this.tagNameTextInput.nativeElement.hidden = true;
this.tagNameTextInput.nativeElement.previousElementSibling.hidden = false;
let initialValue = event.target.childNodes[0].nodeValue.trim();
event.target.hidden = true;
event.target.nextElementSibling.hidden = false;
event.target.nextElementSibling.value = initialValue;
console.log(index);
// this.checkListNameHidden = true;
// this.checkListNameTextInput.nativeElement.value = initialValue;
// this.checkListNameTextInput.nativeElement.focus();
event.stopPropagation();
}
How to solve this?
You have multiple children, So you need to use #ViewChildren instead of #ViewChild.
Also in your ngFor loop you do not have unique template reference #tagInput. Use QueryList with ElementRef.
Try : #ViewChildren('tagInput') tagNameTextInput: QueryList<ElementRef>;
instead of
#ViewChild('tagInput') tagNameTextInput: ElementRef;.
Import QueryList from #angular/core.
Like this import { Component, QueryList } from '#angular/core';
the best aproach is add a new property to "item", (e.g. called "editing") so
<li *ngFor="let item of Array let i = index">
<span>
<label *ngIf="!item.editing" (dblclick)="item.editing=true;">
{{item.tag}}
</label>
<input *ngIf="item.editing" [(ngModel)]="item.tag" type="text" (blur)="item.editing=false" />
</span>
</li>
See several things:
1.-in a click of label, the variable becomes true, so the inpùt is showed
2.-in blur of item, the variable becomes false, so the label is showed
3.-Use [(ngModel)] to relation between the input and the value

How to initialize ng-model of input checkboxes in an ng-repeat loop

I've run into an issue when creating multiple input[checkbox]es for a list of items in angular with ng-repeat and attaching an ng-model:
<li ng-repeat="item in items">
<a ng-href="#/{{item.id}}" > {{ item.id }} </a>
<input type="checkbox" ng-model="selectedMessages[item.id]"/>
</li>
The issue here is that selectedMessages[item.id] is only initialized and set when the checkbox is clicked once.
The reason this is necessary is that I would like to toggle all checkboxes with a single comand like so:
$scope.toggleCheckboxes = (state) ->
for key, val of $scope.selectedMessages
$scope.selectedMessages[key] = state # true or false
Let's say I have 3 checkboxes, and click 1 once, 2 twice, and 3 never, then said object will look like this:
$scope.selectedMessages = {
"1" : true,
"2" : false
}
So obviously, $scope.toggleCheckboxes(true) will only work for those checkboxes.
Is there a good way to initialize this ng-model for multiple checkboxes?
You can use ng-init to populate the array. I used $index rather than making up a bunch of data with id properties...adjust your code accordingly
<input type="checkbox"
ng-model="selectedMessages[$index]"
ng-init="selectedMessages[$index]=selectedMessages[$index]||false" />
JS
$scope.selectedMessages=[];
$scope.checkAll=function(){
var msgs = $scope.selectedMessages
msgs.forEach(function(elem, idx){
msgs[idx] =true
})
}
DEMO

sub ng-repeats, getting (checked) checkbox values in angular

I have some nested ng-repeats I am working with and the third level down is a grouping of checkboxes. Initially I am sent an array of options for the checkboxes so I do this:
<div class="fadingOptionsHere" ng-repeat="fading in fade.options">
<input type="checkbox" ng-model="fadingsHere" value="{{fading.id}}">{{fading.name}}
</div>
I am tyring to find a way to ONLY get the values of the selected checkboxes back. It would be super ideal if I could just replace the nested options array with an array of only the selected items, so I could just send the json object back like that.
This is the third level down of nesting so I'm having trouble tracking these guys. How would I be able to get only the selected values (as the fading.id) of the select boxes for each iteration of the ng-repeat?
I keep trying to reference the fadingsHere model with no success.
Thanks!
You can do this in this way.
In HTML do like below.
<ul>
<li data-ng-repeat="record in records">
<input type="checkbox" ng-model="selected[record.Id]"> {{record.Id}}
</li>
</ul>
And in controller you have to add selected property.
function MyCtrl($scope) {
$scope.records = [ { "Id": 1, }, { "Id": 2 }, { "Id": 3 } ];
$scope.selected = {};
$scope.ShowSelected = function() {
return $scope.selected
};
When you read the selected property you will get the selected list.
Demo
you could use checklist model directive like
<input type="checkbox" class="form-control"
checklist-model="transaction.jobData[attribute.key]"
checklist-value="checkBoxAttributes.code">

knockout.js checkboxes used to control enabled/disabled state of input fields

I am trying to bind a checkbox to each line in a list of objects, in a very similar fashion to a question asked/answered here: Binding a list of objects to a list of checkboxes
Essentially, as follows:
<ul data-bind="foreach: phones">
<li>
<input type='text' data-bind="attr: {value:phone}, disable: $root.selectedPhones"/>
<input type="checkbox" data-bind="attr: {value:id}, checked: $root.selectedPhones" />
</li>
</ul>
<hr/> selected phones:
<div data-bind="text: ko.toJSON($root.selectedPhones)"></div>
<hr/> phones:
<div data-bind="text: ko.toJSON($root.phones)"></div>
with js as follows:
function Phone(id,phone) {
this.id = id;
this.phone = phone;
}
var phones_list = [
new Phone(1, '11111'),
new Phone(2, '22222'),
new Phone(3, '33333')
];
var viewModel = {
phones: ko.observableArray(phones_list),
selectedPhones: ko.observableArray()
};
ko.applyBindings(viewModel);
The idea being that in the initial state, all of the input boxes are disabled and that clicking a checkbox will enable the input box in that row.
The data is coming from a fairly deeply nested object from the server-side so I'd like to avoid 'padding' the data with an additional boolean ie avoiding new Phone(1,'xx', false)
(a) because it's probably unnecessary (b) because the structure is almost certainly going to change...
Can the selectedPhones observable be used by the enable/disable functionality to control the status of fields in that 'row'?
Hope someone can help....
I have a jsfiddle here
You can create a small helper function which checks that a given id appers in the selectedPhones:
var viewModel = {
phones: ko.observableArray(phones_list),
selectedPhones: ko.observableArray(),
enableEdit: function(id) {
return ko.utils.arrayFirst(viewModel.selectedPhones(),
function(p) { return p == id })
}
};
Then you can use this helper function in your enable binding:
<input type='text' data-bind="attr: {value:phone}, disable: $root.enableEdit(id)"/>
Demo JSFiddle.

Categories

Resources