$watch or ng-model binding issue? - javascript

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">

Related

How to access an HTML element that is dynamically filled with values?

I've read lots of stackoverflow questions with no luck. My problem is, I have an HTML page in which I have
<select id="myid"></select>
and there, there's a Firebase command that retrieves names of values i need, and put it inside the <option> like HERE:
reference.on("child_added", function (childSnapshot){
var key = childSnapshot.key;
var opt = document.createElement('option');
opt.textContent = key;
document.getElementById('myid').appendChild(opt);
});
Now, i need to somehow access these values, that by the way are correctly appearing in both HTML and my site, however:
var val = document.getElementById('myid').value;
console.log(val);
It always returns blank in console. I don't know how else can I access it. Whenever I type those values in <option> by myself in HTML, everything works as it should and console returns the names that are in database.
#edit: as far as i tried to crack it, it seems to do with the fact that javascript cannot access elements, that for javascript itself aren't yet loaded, but i tried doing window.onload and other similar ones and they don't help.
You can use AngularJS, with directive $scope.watch, i will write a simple example of how to use and the link of documentation, if you have any question talk back to me!
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
AngularJS Documentation
I hope help with this :)

adding a class after email is validated using jquery

I'm trying to use jQuery for email validation in a form field
$(document).ready(function() {
var email = new RegExp("[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$");
var value = $("#email_address").val();
$("#email_address").on("keypress", function() {
if(email.test(value)) {
$("#email_address").parent().addClass("has-success");
}
});
});
However, the has-success class doesn't get added. I've tried each line of code individually in the console and they all seem to be doing/pointing to the right thing. It's when it's all put together that it doesn't seem to work.
You load the value on jQuery's DOM ready and never load it again.
You need to test the current value, not the one that's there when the DOM is ready, roughly:
$("#email_address").on("keypress", function() {
if(email.test($(this).val())) {
$("#email_address").parent().addClass("has-success");
}
});
Unrelated, but personally I'd wrap up the email test in a function so instead of saying email.test(xxx) you could read it more naturally like validEmail(xxx) etc.

AngularJS one-way binding not working properly

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;
});
};

Determine if the content in a (dojo) dijit.Editor is different from the initial value

I have a form containing many dijit.form elements and also a dijit.Editor. The form is initially filled with data that I get from the server. The user can change the content and then submit this back to the serer. A classic use case.
When the user submits the form I need to only send the changed data. The problem with the dijit.Editor is that it sometimes changes the initial content even if the user did not make any changes. For example:
The initial content entered in the dijit.editor is this:
"Gesegmenteerde rand, 115 mm~Max 13280 U/min, 80 m/sec</br>~Drooggebruik"
And when retrieving the content like this editorObj.get('value'); it returns this:
"Gesegmenteerde rand, 115 mm~Max 13280 U/min, 80 m/sec<br />~Drooggebruik"
As you can see the </br> is changed to <br />. I know the original value is wrong, but that's because the source sucks and that is out of my control.
So my question is: is there an easy way to check if the content has indeed been changed by the user instead of just by dijit.Editor itself.
Something like this (on the editor markup) works:
onkeypress="MyObject.setDirty(true);"
And just keep track of it on MyObject.isDirty.
This does have the drawback that if the user types into the editor and then modifies everything to be exactly as it was originally, the value will be wrong (ie, true, whereas content is back to original), but it is sufficient for most purposes.
Well if you just want to check IF the user modified something you could try that :
var editorIsDirty = false;
var someConnect = dojo.connect(myEditor, "onChange", this, function(newValue){
if(originalSource != newValue){
editorIsDirty = true;
return;
}
editorIsDirty = false;
});
something like that, you get the idea ;)
What I ended up doing is was adding two extra attributes to the Editor:
dijitObj.set('originalValue', value);
dijitObj.set('value', value);
dijitObj.set('uneditedValue', dijitObj.get('value'));
In the read out of the value of the the editor I use these to determine if something changed at all:
var value = dijitObj.get('value');
if (dijitObj.get('uneditedValue') === value) {
// The value hasn't changed, so we send the original value
value = dijitObj.get('originalValue');
}

Variable not updating in script string, yet it updates

Very confused here.
I have a search box which reads a list of school names from my database. When I select a school, the id (from the db) gets put in a hidden textbox.
I also have a search box which reads a list of courses from my database. However, I made the query so that it only reads the courses from the selected school.
It does that, in theory.
I was planning to pass the school id, which I grab from the hidden box, to the search script which in turn passes it to my database query. However, the variable I put my school id in doesn't seem to be updating.. yet it does. Let me explain.
I come on the page. The school for my test account has id 1. The id number in my hidden box is indeed 1. I search for a school which I know has some courses assigned to it: the id number in the box changes to 3.
I have a JS variable called school_id which I declared outside of my $(document).ready. I assume that means it's global (that's what I got taught even though SO told me once it isn't really the correct way to do this. Still have to look into that). I wrote a function which updates this variable when the school search box loses focus:
$("#school").blur(function() {
school_id = $("#school_id").val();
});
A quick javascript:alert(school_id); in my browser bar also shows the updated variable: it is now 3 instead of 1.
Onto the search script part of my page (excerpt of the script):
script:"/profiel/search_richting?json=true&limit=6&id=" + school_id + "&"
As you can see, I pass the school_id variable to the script here. However, what seems to be happening is that it always passes '1', the default variable when the page loads. It simply ignores the updated variable. Does this string get parsed when the page loads? In other words, as soon as the page loads, does it actually say &id=1? That's the only idea I can come up with why it would always pass '1'.
Is there a way to make this variable update in my script string? Or what would be the best way to solve this? I'm probably missing out on something very simple here again, as usual. Thanks a lot.
EDIT
Updated per request. I added a function getTheString as was suggest and I use the value of this function to get the URL. Still doesn't work though, it still seems to be concatenating before I get a chance to update the var. HOWEVER, with this code, my ajax log says id:[object HTMLInputElement], instead of id:1. Not sure what that means.
<script type="text/javascript">
var school_id;
$(document).ready(function() {
$("#school").blur(function() {
school_id = $("#school_id").val();
});
// zoekfunctie
var scholen = {
script:"/profiel/search_school?json=true&limit=6&",
varname:"input",
json:true,
shownoresults:false,
maxresults:6,
callback: function (obj) { document.getElementById('school_id').value = obj.id; }
};
var as_json = new bsn.AutoSuggest('school', scholen);
var richtingen = {
script: getTheString(),
varname:"input",
json:true,
shownoresults:true,
maxresults:6
};
var as_json2 = new bsn.AutoSuggest('studierichting', richtingen);
});
function getTheString() {
return "/profiel/search_richting?json=true&limit=6&id=" + school_id + "&";
}
</script>
This is because the URL is static, it is not updated as the ID changes.
You should update the URL as part of the code you wrote to get the ID:
$("#school").blur(function() {
school_id = $("#school_id").val();
// update URL here ...
});
Aren't you concatenating script:"/profiel/search_richting?json=true&limit=6&id=" + school_id + "&" before the event is fired and the var updated?
Okay. So the problem was my third party plug-in instead of the code I wrote. I fixed this by editing the code of the autoSuggest plugin so it now includes my id field in the AJAX request.
var url = this.oP.script+this.oP.varname+"="+encodeURIComponent(this.sInp)+"&id="+ $("#school_id").val();
Thanks to everyone who tried to help me out!

Categories