currently struggling with a thing that I thought would be easy...
I'm trying to update a value in a ng-repeat directive using a select dropdown.
Here is what the HTML looks like:
<div ng-repeat="groupeQuestions in questionnaire.GroupesQuestions" class="umb-group-builder__group">
<select ng-model="groupeQuestions.TypeQuestionId" ng-options="value.Id as value.Description for value in typesQuestions ">
</select>
<input type="text" ng-model="groupeQuestions.TypeQuestionId"/>
<button ng-click="saveGroupeQuestions({{groupeQuestions}})" >Sauvegarder</button>
<button ng-click="deleteGoupeQuestions({{groupeQuestions.Id}})" >Supprimer</button>
</div>
And here is the js controller function used to update the item :
$scope.saveGroupeQuestions = function (groupeQuestions) {
console.log(groupeQuestions);
surveyPluginResource.saveGroupeQuestions(groupeQuestions).then(function (response) {
$scope.questionnaire = response.data;
navigationService.syncTree({ tree: 'survey', path: [-1, -1], forceReload: true }).then(function (syncArgs) {
navigationService.reloadNode(syncArgs.node);
});
});
};
Somehow, I'm missing something with the binding thing, because if I change the value in the dropdown, the textbox is updating as well.
But when it reaches the controller, the console.log() displays the item which does not contain the new groupeQuestions.TypeQuestionId.
I'm new to js and angularJs too, so is there something on binding that I've missed?
Don't use {{}} interpolation when passing a scope variable to a function
<button ng-click="saveGroupeQuestions(groupeQuestions)" >Sauvegarder</button>
<button ng-click="deleteGoupeQuestions(groupeQuestions.Id)" >Supprimer</button>
Related
I need to make some inputs by ng-repeat, and in my json file I have in object where is a property called name, like this:
"url":"find_company",
"values":[
{
"name":"company name",
"type":"input_search"
},{
"name":"company_phone",
"type":"input_search"
}
]
I want to make search in DB, in search you can find by any field or by two or more field. Field called the same as property of object. So by ng-keyup I need to send to my function
search(field, value)
two arguments. I want to do something like this
<div ng-repeat="value in param.values">
<input ng-if="value.type == 'input_search'"
ng-keyup="search(value.name, this.text)"
type="text">
How can a send to function text of this input without using ng-model? Where this.text is value of input.
since you are using ng-keyup, you can retrieve input value with $event.target.value.
comment: this is fit for normal event like onclick, but not fit for angular.
refer the below example.
angular.module("app", [])
.controller("myCtrl", function($scope) {
$scope.showValue = function(val) {
alert(val);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<input type="test" ng-keyup="showValue($event.target.value)">
</div>
This is how you do it with ngModel:
<div ng-repeat="value in param.values">
<input ng-if="value.type == 'input_search'" ng-model="value.val" ng-keyup="search(value)" type="text">
And in your controller:
$scope.search = function( item ) {
console.log( item.val ); // Here you have the value using ngModel
console.log( item.name ); // Here you have the "name" property of the element inside the loop
}
As you can see, you CAN use ngModel and by passing the object itself to the function you can access its properties from the function in the controller.
Note that there's that this.text in the view - I don't know what it is exactly so I dropped it from the example to make things clearer, but you can use it in your code of course.
I know the question said without using ng-model. But I suspect you may want this because you want to customize when data-binding occurs. If that's the case, you can use ng-model-options with ng-change:
<input type="text" ng-model="yourModel" ng-model-options="{ updateOn: 'keyup' }" ng-change="search()" />
ng-change fires when the model has been updated, which is after keyup in this case. So the value of yourModel will be up to date when search() executes.
I'm using Angular to generate some inputs and populate them with data using ng-repeat. I also want to bind the data inside the input to a save changes button which takes parameters provided by ng-model directives. save changes button prints the passed arguments using the built-in JS arguments object. For some reason, unless I change the text inside the input box, the output is [undefined, undefined]. Once I change the text inside the input boxes, the correct output is printed. Why is that?
JSfiddle code.
HTML:
<div ng-app="myApp" ng-controller="MainCtrl">
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.men = [{
name: "jon snow",
status: "depands"
}, {
name: "rob stark",
status: "dead"
}];
$scope.save = function() {
console.log(arguments);
}
});
This is not recommended but for your specific requirement you can use ng-init to bind ng-value to your model
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name" ng-init="mname = man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status" ng-init="mstatus = man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
This wouldn't bind your changes to the original model.
Fiddle
ngModel doesn't update untill you use a key to change it, or set it from your controller. Because you are setting the field of the input using ngValue, it doesn't register to your ngModel untill you change it.
This problem is similar to how most datepickers don't work with ngModel, as they set the field with DOM-manipulation and NOT by inserting the value by "key".
You can easily fix this by using the following HTML instead:
<label>name</label><input type="text" ng-model="man.name"><br>
<label>status</label><input type="text" ng-model="man.status"><br>
I simply removed the ngValue and linked the ngModel to your "man".
I'm using tabset directive of angular js and using twitter bootstrap slider in tab,
My slidestop event is not calling but it's working well outside tab.
I know that tabset directive have its own scope , but dont know solution of following problem:-
<tabset class="tab-container">
<tab heading="tab1">
<div class="form-group">
<label>any Level</label>
<div class="input-group w-md">
<input id="slider" ui-jq="slider" ui-options="{min: 0,max: 10,step: 1,value: {{any_level}}}"
class="slider slider-horizontal form-control" type="text"
ng-model="any_level"> {{any_level}}
</div>
</div>
</tab>
</tabset>
controller code
......
angular.element("#slider").on('slideStop', function(data){
alert('asdasd');
})
problem is - alert is not coming when slider inside tab,alert is comming when slider outside tab
i am using this slider
Thanks
i have solved using ui-event directive to fire slidestop event
Html Code
<input id="slider"
ui-event="{slideStop: 'alertChange($event)'}" ui-jq="slider"
ui-options="{min: 0,max: 10,step: 1,value: {{any_level}}}"
class="slider slider-horizontal form-control" type="text" ng-model="any_level">
{{any_level}}
Controller Code
$scope.alertChange = function(data){
console.log(data.value); // i can get slider value on slidestop
}
Just don't use angular.element in an angular app.
EDIT : This isn't really working with ui-slider. Till ui-slider is work in progress i just woudn't use it.
Add this to your input :
ng-change="alertChange()"
And this to your controller :
$scope.alertChange = function(){
alert('hi');
}
What wasn't working ? In most of the case an angular.element will try to bind your even to the element too early. Your DOM "#slider" element isn't probably loaded when your try to bind.
EDIT An alternative :
First, after paying more attention i wouldn't recommend this slider at all.
This is actually a work in progress and isn't really reliable.
I made you an exemple of a html slider with binding in this plunker
You slider looks like this :
<input id="slider"
ng-model-options="{ debounce: 100 }"
min="0"
max="100"
ng-init="any_level = 0"
ng-change="alertChange()"
type="range"
ng-model="any_level">
This will update the model each time the value will not change for 100miliseconds. You need this to avoid firing too much ng-change function.
In your javascript you just need to declare your function
$scope.alertChange = function(){
console.log("I changed !");
//or anything else you want to do
}
I know this is not a solution but an alternative. It's not sexy as the other slider, but at least it works.
Hope it helped you.
The slider you are using has an example demonstrating how to do this. Take a look at box "12" on this page: http://angular-ui.github.io/ui-slider/demo/demo.html
In your controller you can add the following:
$scope.slider = {
'options': {
stop: function (event, ui) { $log.info('Slider stop'); };
}
And your HTML you must reference slider.options so your callback is fired:
<div ui-slider="slider.options"
min="0" max="50" ng-model="any_level"></div>
I have created radio buttons in angularjs using array of objects using ng-value and ng-model.
`
<div ng-controller="DemoController">
<div ng-repeat="detail in details">
<input type="radio" ng-model="$parent.selectedVal" ng-value="detail" name="test">
</div>
{{selectedVal}}
</div>
`
On selection of radio button model is populated with corresponding object value. But I am not sure how to initialize it using controller with object.
var app = angular.module('myApp', []);
app.controller("DemoController",DemoController);
function DemoController($scope) {
$scope.selectedVal={name:"Def",age:4} ;
$scope.details=[{name:'Abc',age:2},{name:'Xyz',age:3},{name:'Def',age:4}];
}
You should reference the selected value from the details array instead of creating a new instance:
$scope.details = [{ name:'Abc', age:2 }, { name:'Xyz', age:3 }, { name:'Def', age:4 }];
$scope.selectedVal = $scope.details[2];
This will select the last of the 3 radio buttons. Also if both details and selectedVal are defined within the same scope you should update your radio button as well, it's quite unclear why you referenced selectedVal from a $parentScope:
<input type="radio" ng-model="selectedVal" ng-value="detail" name="test" />
And here's the updated fiddle: https://jsfiddle.net/sb3krc8c/2/
The following code is getting data from Firebase and binding it to $scope:
'use strict';
angular.module('costumeQueenApp')
.controller('ActorByUserIdActorIdCtrl', function ($scope,$routeParams,FireRef) {
var userId = $routeParams.user_id
var actorId = $routeParams.actor_id
var base = FireRef.actorById(userId, actorId)
$scope.base = base
$scope.base.$bind($scope, 'actor')
})
And uses the following template code to display the data (Note: uses AngularUI-Bootstrap):
<accordion-group heading="Sizes">
<div ng-repeat="(key, value) in actor.sizes">
<label for="key">{{key}}</label> <input type="text" ng-model="value" />
</div>
</accordion-group>
The problem is that three-way data-binding is not working for the items inside the ng-repeat div. If I have an input field that uses the fully-qualified field in an input field, e.g., actor.sizes.waist, everything works as expected.
How do I make the data binding work properly?
If you replace value then you have essentially done: $childScope.value = somethingNew. Like any other JavaScript reference, this dose not modify the contents of the original object.
To put it another way, setting value above is equivalent to this:
var items = [{label: 'a'}, {label: 'b'}, {label: 'c'}];
angular.forEach(items, function(v, k) {
v = {foo: bar}; // does nothing to items! Only modifies the local variable `v`
});
You can fix this when using angularFire by using $set:
<accordion-group heading="Sizes">
<div ng-repeat="(key, value) in sizes">
<label for="key">{{key}}</label> <input type="text" ng-model="value" ng-change="actor.$child('sizes/'+key).$set(value)" />
</div>
</accordion-group>
Note that ng-change feels a bit hackish here but investigating that didn't feel necessary to illustrate the solution.
Also, if you are using $bind to sync data, or you want to control the timing of the sync event, you can just set the data on the parent object without a $set call:
<accordion-group heading="Sizes">
<div ng-repeat="(key, value) in sizes">
<label for="key">{{key}}</label> <input type="text" ng-model="value" ng-change="actor.sizes[key] = value" />
</div>
</accordion-group>