How to bind Array from angular $scope to the input - javascript

I have an array in $scope, say
$scope.my_array = ["val_1", "val_2", "val_3"]
To bind this array input element, I used ng-model:
<input type="text" ng-model="my_array">
Now I want it to be display the array values as comma separated in input box, but nothing displays. Is this even possible?
In ng-repeat, it is iterating the values, so the array is available to the view.
EDITED: Thanks, the normal way is working for array binding. But in my case I was first using empty array:
$scope.my_array = []
Then, on ng-click function, I am grabbing the data-* attribute from the clicked element and pushing it to the array:
var item = $(".some-class").data("field-type");
$scope.my_array.push(item)
Iterating over this is working fine, but not working while setting to the input.

Look at another topic where two-way filtering is explained in details: How to do two-way filtering in angular.js?
in brief you should use ngModels' $parsers and $formatters collection to be able make .join(", ") before setting to input and to make .split(/, */) before setting value back to the model.

This problem has been solved, I used
$scope.my_array = $scope.my_array.concat(item)
Instead of using .push() method.
I don't know if the push method of the array is a problem, but after concating the value into array, worked for me, now the array values are visible in input field.

Related

how to bind values to an object in order of insertion

I have some inputs, and I want to get data in order of insertion, for example: if I insert the value bbb then the value aa I want to get bbb befor aa
I search in the net and find that this order is ensured using Mapbut I don't know how to use it with ng-model.
thank you in advance.
EDIT
I'm using an object that store the value of the inputs and a customized key passed with value
here is an example, if you insert the values in input 3 then 2 then 1, and click ok, in the console the output will be ordered in an alphabetic order
As stated by #czosel, javascript objects are not ordered, and are usually sorted by alphabetical order of the keys. Therefore, your best solution is probably going to involve going beyond using the ng-model directive as is.
Here are two possibilities you could try out:
Solution 1
In every <input /> place an ng-blur directive that will determine the input's order. For instance:
HTML
<input ng-blur="onBlur('model1')" ng-model="model1" />
<input ng-blur="onBlur('model2')" ng-model="model2" />
controller.js
app.module('myModule').controller('myCtrl', ['$scope', function($scope) {
$scope.count = 0;
$scope.onBlur = function(key){
// check if anything was entered
if($scope[key]){
// make sure this is first time data was entered into this input
if(!$scope[key].order)
$scope[key].order = $scope.count++;
}
};
}]);
Solution 2
Store the values in an array. Similar to the first solution, but instead of keeping count, you would forego the ng-model altogether and manually add the value to an array (after checking that it doesn't already exist, which gets a little tricky with an array). Of course you also have to handle updates yourself, so the first method is definitely going to be simpler. The lodash library will probably be of much help if for some reason you decide to choose this approach.
Lots of luck!
JavaScript Object properties have no guaranteed order, see this answer.
Try using an array instead.
You can Queue(First in First Out) to get data in the order of insertion. Trigger a function and store the values binded in ng-model into queue.
Ex: ng-model = data // here data will be bbb
var queue = [];
function bind(value){
queue.push(value); // value will be bbb
}
if user enters aa then again bind function needs to be called to push the value inside queue
U can get the values in the order of insertion.

Ember filterBy - using more than one value to filter

How can I use more than one value to filter a list using the filterBy function?
My scenario is - I have a list of consoles which I want to filter based on the console_id.
Unfortunately, I don't have control over the JSON so each consoles has a different ID. I would like to loop through the Console IDs within the nested assignedConsole JSON and then filter through the root assignedConsole JSON.
I can get the console ID of the first object and place it into the filter but I don't know how I can use two values
I have created a emberjs bin to demonstrate my problem: http://emberjs.jsbin.com/kojute/2/
After some clarification from my previous answer, I realized you want to filter by console instead of filtering the assignedConsole values. My suggestion is to add a selectedConsole property on the controller, and display the array of assignedConsoles for the selected console.
Working JSBin: http://jsbin.com/nuroyuvuta/9
EDIT: See my other answer for the working solution!
I would suggest creating a computed property on your model or your controller that flattens that nested structure for you:
allConsoles: function() {
return this.get('consoles')
.mapProperty('assignedConsoles').reduce(function(a, b) {
return a.concat(b);
})
.uniq();
}.property('consoles.#each')
This will first get all of the items from the consoles property, then map all of their assignedConsoles to an intermediate value, which is then reduced by adding all the assignedConsoles together. The final uniq() call just removes any duplicates found in the array.

Editing a delimited string using multiple input fields in AngularJS

I am trying to do the following quite unsuccessfully so far.
I have an string that is semicolon separated. Say a list of emails, so
'email1#example.com;email2#example.com;email3#example.com'
What I am trying to accomplish is split this string (using split(';')) into an array of strings or array of objects (to aid binding). Each of the items I would like to bind to different input elements. After editing I want to read the concatenated value again to send to my backend.
Problem is that when editing one of the split inputs, the original item value is not update (which makes sense as I am guessing the individual items are copies of parts of the original), but I am wondering if there is a way to do something like that.
Note that I want this to go both ways, so watching the individual inputs and updating the original one manually, would just fire an infinite loop of updates.
I have tried a few different ways, including creating an items property get/set using Object.defineProperty to read and right to the string (set was never fired).
take a look at this plnker
You can construct a temporary array on each field update in order to do the string replacement of the old segment with the new value. In order to tackle the lost focus problem you will have to use the ngReapeat's track by $index. The internal array will not be recreated unless you add the separator to your original string.
Here is the complete solution on Plunker
Your main issue is your ng-model attribute on your repeated input element. I would start with making use of ng-repeat's $index variable to properly bind in ng-model. In your original Plunker 'name' is NOT a scope property you can bind to, so this should be changed to ng-model="names[$index]"
Here is a Plunker to reflect this. I made quite a few changes for clarity and to have a working example.
NOTE: You will find that when editing fields directly bound to a repeater, every change will fire a $digest and your repeated <input> elements will refresh. So the next issue to solve is regaining focus to the element you are editing after this happens. There are many solutions to this, however, this should be answered in a different question.
Although binding to a string primitive is discouraged, you could try ng-list.
<form name="graddiv" ng-controller="Ctrl">
List: <input name="namesInput" ng-list ng-model="vm.names"/>
<ul>
<input ng-repeat="name in vm.names track by $index" ng-model="name" ng-change="updateMe($index, name)"/>
</ul>
You'll need both track by $index and an ng-change handler because of the primitive string binding.
function Ctrl($scope) {
$scope.vm = {}; // objref so we can retain names ref binding
$scope.vm.names = ['Christian', 'Jason Miller', 'Judy Dobry', 'Bijal Shah', 'Duyun Chen', 'Marvin Plettner', 'Sio Cheang', 'Patrick McMahon', 'Chuen Wing Chan'];
$scope.updateMe = function($index, value){
// ng quirk - unfortunately we need to create a new array instance to get the formatters to run
// see http://stackoverflow.com/questions/15590140/ng-list-input-not-updating-when-adding-items-to-array
$scope.vm.names[$index] = value; // unfortunately, this will regenerate the input
$scope.vm.names = angular.copy($scope.vm.names); // create a new array instance to run the ng-list formatters
};
}
Here's your updated plunkr

In Angular, how do I efficiently split input items into an array

When binding input value to an ng-model like so:
<input type="text" ng-model="array">
how do I bind the input text as an array? So if I input one, two, three, the resulting model will be [ "one","two","three ].
Right now this is how I'm achieving this:
<input type="text" ng-model="string" ng-change="convertToArray()">
And in my controller:
$scope.convertToArray = function(){
$scope.array = $scope.string.split(',');
}
It works fine but I don't think it's best practice because I'm making a $scope.string variable and then hardcoding the destination array.
Is it possible to just have the input's model set into array and then have the input pass through the function before being bound to the scope?
ngList will do exactly what you want.
Text input that converts between comma-separated string into an array of strings.
No. Since your input will be a string from the user, you need to manually convert it to array or any other format.
Similar discussion and other approach is discussed here. probably this might help. (see accepted answer in this)
How do I set the value property in AngularJS' ng-options?

How can I bind the selected text of a Select box to an object's attribute with Knockout JS, or anything else?

I have a select box pull down that I'm populating with a JSON list returned from a stored procedure, but unfortunately when I update the linked object I need to return the selected text of the pulldown, not the selected index like one would think (poor database design, but I'm stuck with it for now and cannot change it).
Does anyone have any ideas what I can do to keep the selected text synced with the appropriate javascript object's attribute?
You could keep both, the value and the text, if you use subscribers.
For instance, if each of your javascript objects look like this:
var optionObject = {
text:"text1"
value: 1
}
Then your binding would look like:
Where 'OptionsObjects' is a collection of optionObject and selectedOption
has two observable properties: text and value.
Finally you subscribe to the value property of the selectedOption:
viewModel.selectedOption.value.subscribe(function(newValue){
var optionText = viewModel.OptionsObjects[newValue].text;
viewModel.selectedOption.text(optionText);
});
Then if you want to see the new selected option text when the value is changed,
you could have a binding as follows:
<span data-bind:"text:selectedOption.text"></span>
In your particular case you would return selectedOption.text().
So yes, you got what I was getting at. Use the text as the value for the select options rather than using an index. The value really should be something useful, I can't think of any case where I've ever used an index. A number sure, but a number that relates to the application's models in some way (like an id from a database), not to the number of items in the select box.
Well done.

Categories

Resources