AngularJS one-way binding not working properly - javascript

I'm trying to bind an input (one-way), whoever if I change its value its no longer binding properly
//controller => on row click => change input
$scope.getNote = function (note)
{
$scope.currentNote = note;
};
//view
<input type="text" value="{{currentNote.Title}}" >
This is the scenario, getNote is being called and the input is being filled properly. However, when I change the value of the input and call getNote again the input doesn't show the new value even tho its value attribute contains the correct value. So somehow its not showing the correct value to the end user.
eg:
1- First Value from GetNote = "Hello World"
2- I change the value of the input to "Foo" as a normal user
3- Call GetNote again and the I get value="Hello World" but on the screen it displays "Foo"
Hack Solution:
//controller object value copy using jquery
$scope.currentNote = jQuery.extend({}, note);
//view
<input type="text" ng-model="currentNote.Title" >
Am hoping for an Elegant solution

I think you should try with ngValue directive, as sbaaaang said. But without curly braces (documentation here: https://docs.angularjs.org/api/ng/directive/ngValue).
Edit:
And maybe if you just want to use one-way data binding a div will be enough for your purposes, and not an input. Then you can style it as you want.

use ng-value="" instead of value="" should fix
i would do:
$scope.getNote = function (note)
{
$scope.currentNote = note;
};
//view
<input type="text" ng-model="currentNote.Title" ng-value="currentNote.Title" />
If you still getting problems try also:
$scope.getNote = function (note)
{
$scope.$on(function () {
$scope.currentNote = note;
});
};

Related

Angular uib typeahead, typeahead-is-open not working

I have a angular uib-typeahead. Here is a link to plunkr that I created.https://plnkr.co/edit/8XwhSXsZlyd0oKSljS9t?p=preview.
I have used typeahead-is-open property.
What I want is when I click on the uib-typeahead it should open and display all the values. I am assuming setting the typeahead-is-open to true does this job. Is this correct? Currently the typeahead does not open up on setting typeahead-is-open to true.
Here is my html
<input ng-click = "myFunc()" click-outside="typeaheadIsOpen = false;" type="text" ng-model="selected" uib-typeahead="state for state in states | filter:$viewValue | limitTo:8" typeahead-is-open="typeaheadIsOpen" class="form-control">
My JS
$scope.myFunc = function() {
$timeout(function() {
$scope.typeaheadIsOpen = true;
$scope.$digest();
})
}
I have bound the typeahead-is-open to "typeaheadIsOpen" variable. On clicking on the typeahead I invoke myFuc() which sets the variable typeaheadIsOpen to true.
But the typeahead does not open. Is there something I am doing wrong?
It seems that you can't control whether the typeahead popup is shown or not using typeahead-is-open attribute. Here is the relevant part from source code:
UibTypeaheadController
//binding to a variable that indicates if dropdown is open
var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;
...
scope.assignIsOpen = function (isOpen) {
isOpenSetter(originalScope, isOpen);
};
This attribute is used to obtain expression used to update the scope when typeahead is open, but is not used to get value from scope and no relevant watcher is setup.
Sadly, I'm still using angularjs in 2021. I ended up finding a hack based on these threads on it
https://github.com/angular-ui/bootstrap/issues/6619
https://github.com/angular-ui/bootstrap/issues/759
Given a typeahead input
<input class="form-control address_input"
type="text"
typeahead-editable="true"
typeahead-on-select=...
In the controller in angular that handles this, I created a function like this
function _forceDropdownOpen() {
const controller = $(".address_input").controller('ngModel');
const old = controller.$viewValue;
controller.$setViewValue(old +' ');
controller.$setViewValue(old);
}
It simply mimicks adding space to the result and then removing that space.
Here is an example of my app before and after. My use case was after the third letter typed, my code sends an HTTP request. When that request returns, and if it has results, I call this method to open the dropdown.
Before: dropdown does not open until a fourth letter is typed
After: opens immediately on results

How to clear an Input after form submission in Aurelia

Is there an Aurelia way to accomplish what I am trying to do? After I click add, I want the input to be set back to zero. Here is the app.js file
export class App {
constructor() {
this.message = 'Hello World!';
this.array = [];
this.array.push("Hello");
}
addToArray()
{
this.array.push(this.hello);
hello = "";
}
}
I tried setting the var hello back to an empty string, thinking Aurelia had them two way bounded. But then I thought that was silly, because you might want to mutate/manipulate the variable while in the function, and you wouldn't want the user to see it, so I guess setting hello back to an empty string wouldn't work. Here is the html.
<form submit.trigger="addToArray()">
<input type='text' value.bind="hello">
<input type='submit' value="add">
</form>
<ul>
<li repeat.for="a of array">${a}</li>
</ul>
It turns out they are bounded! Simple answer here, i needed to use this.hello = ""
Potentially, the model wouldn't update until the function has finished running, my guess is this is how it works. So as long as the bounded variable is set to something user friendly at the end of the function you should be fine making any changes to the value during execution

$watch or ng-model binding issue?

I basically have a very complicated set of tabs with various input controls but lets not worry about this for now. For now let consider simple input wtching issue I am baffled by.
For example:
<input type="text" placeholder="Associate some tags please" data-ng-model="tag" data-ng-maxlength="250">
I am try to detect if user has typed something into my input:
$scope.$watch('tag', function () {
//$scope.$watchCollection('tag', function () {
console.log('tag changed');
});
But I seem to get zero response. However, when I perform my save operation I always seem to get the value user typed in.
Is a case of ng-model not binding correctly or is it that I am not $watching it correctly?
Also after I've performed my save operation I try to clear what user typed in for the tag with:
$scope.tag = '';
But that doesn't seem to work for some reason as though $scope.tag doesn't exist.
PS: When I say save operation I am actually performing a array.push() into an object which later gets saved by a service.
For example:
$scope.checkSaveTag = function (tag) {
...
// checked for duplicate tag beforehand
$scope.myForm.Tags.push(tagObj); // complicated form object
$scope.tag = ''; // tag input control
...
};
Any chance that the tag is an object or an array? If that is the case, you'll need to do a deep $watch, e.g:
$scope.$watch('tag', function () {
console.log('tag changed');
}, true);
Try like this
Controller
$scope.form={
tag:''
}
$scope.$watch("form.tag",function(newVal,oldVal){
console.log(newVal);
})
Html
<input type="text" placeholder="Associate some tags please" data-ng-model="form.tag" data-ng-maxlength="250">

Protractor Get Model Value

I am new to ProtractorJS.
What I am trying to do is trying to get the value of a disabled input element.
This input element is bound to a model. Initially this input element is empty; then after some action the model value is updated (and thus displayed in input element). I need to get that value, how can I do that ?
My input element is:
<input class="form-control ng-pristine ng-valid" style="font-size: 11px;" disabled="disabled" type="text" ng-model="Promotion.PrometricID">
I am trying to fetch value by:
element(by.model("Promotion.PrometricID")).getAttribute('value');
But whenever I write the value in console it gives me "[object] [object]".
Can anyone please tell me how to find value in this text box or in model ?
It is just because getAttribute() returns a promise.
You need to resolve it if you want to see the result on the console:
var elm = element(by.model("Promotion.PrometricID"));
elm.getAttribute('value').then(function (value) {
console.log(value);
});
FYI, exploring The WebDriver Control Flow documentation page should clear things up.
this way worked for me:
element(by.binding('Promotion.PrometricID')).getText().then(function (value) {
console.log(value);
})
My solution:
element(by.model('Promotion.PrometricID')).getText().then(function (value) {
console.log(value);
});
Same as the rest except with await
let text = await element(by.binding('Promotion.PrometricID')).getText();
console.log(text);

What is the best way to identify the updater of an observable

Given any knockout example, I want to be able to identify the source of an observable update.
Consider for example this simple code:
HTML
<input type='text' data-bind='value: someValue' />
<span data-bind='text: someValue'></span>
<button data-bind='click: updateValue'>Update</button>
js
var vm = function () {
var self = this;
this.someValue = ko.observable('random value');
this.updateValue = function () {
self.someValue('random value ' + Math.round(Math.random()*10));
}
}
var vmi = new vm();
vmi.someValue('other random value');
ko.applyBindings(vmi);
Fiddle
I want to know if someValuewas last updated via the input tag, the button, or via code.
What do you think would be the best way to do so? (extender, custom binding handler, ...)
Create separate "writable computed observables" for each of those things to modify. See http://knockoutjs.com/documentation/computedObservables.html#writeable_computed_observables. In your write methods for each of these, you can handle differentiation/coordination/syncing between them as appropriate. There might be a better solution though if you described your actual scenario.

Categories