I'm having weird issues that I can't seem to find an explanation for.
I show a popup with a single input which I am binding to a variable on my scope I'm passing the $scope to the popup.
The binding works and I can see the variable that is set and it changes as I type. But as soon as I close the popup and log out that scope variable on the "on tap" function" it seems to go back to its original value.
EDIT: a pen that demonstrated the general issue:
http://codepen.io/anon/pen/ariDh
code:
var sendPopup = $ionicPopup.show({
title: $translate.instant(popupTitle),
subTitle: $translate.instant('POPUP_WITH_MESSAGE_SUBTITLE'),
templateUrl: 'templates/leave-message-popup.html',
scope: $scope,
buttons: [
{ text: $translate.instant('BUTTON_CANCEL') },
{
text: $translate.instant('BUTTON_SEND'),
type: 'button-positive',
onTap: function(e) {
console.log("contact message:" + $scope.contactMessage);
if (!$scope.contactMessage) {
console.log("preventing default");
e.preventDefault();
} else {
$scope.sendData(contactType);
}
}
},
]
});
template:
<input type="text" ng-model="contactMessage" name="message" placeholder="{{'PLACEHOLDER_CONTACT_MESSAGE' | translate}}" required autofocus>
{{contactMessage}}
This amended version of your codepen shows this working: http://codepen.io/anon/pen/rgBLa
Changing the variable to an object that is on the scope that is passed to the popup correctly allows this to then be bound back to the controllers scope when it changes. This is needed due to the way the scope is managed when passed to the $ionicPopup.
$scope.contactMessage = { text: "text" }
Then updated the mark-up to correctly look at this property on the scope.
<input type="text" ng-model="contactMessage.text" name="message">
{{contactMessage.text}}
I hope this helps with your issue.
Related
I have a modal in Ionic that shows a list of country flags for the user to choose, however my ng-click on the language flag don't appear to fire the $scope.function() I have assigned. Here's what I've got:
Showing the modal:
$scope.showLanguages = function() {
var myPopup = $ionicPopup.show({
templateUrl: 'templates/languageSelect.html',
title: 'Language Select',
scope: $scope,
buttons: [
{
text: '<b>Close</b>',
type: 'button-positive',
onTap: function (e) {
return;
}
}
],
cssClass: 'animated bounceInDown'
});
}
My template that displays my flags, with the ng-click on them:
<div class="row">
<button ng-class="getFlagClass(language)" ng-click="setLanguage()" class="col flag-icon flag-icon-squared" ng-repeat="language in data.languages" />
</div>
And finally my ng-click function which is on the same scope as the one that opens the modal (notice the $scope being passed into the modal)
$scope.setLanguage = function() {
alert('test');
}
Can anyone suggest what I might be doing wrong here? This looks like a bug in Ionic but I could be wrong.
Thanks
It turns out it WAS working, but the alert wasn't being shown... I suspect this is because it was within a modal? I don't know.
Anyway, there's nothing wrong with the above code after all.
select2 provides some custom events and i want to be able to listen to them, particularly the 'select2-removed' or better yet its custom 'change' event, and I’ve been searching the internet for some example, but with no luck.
here's what I’ve done so far:
HTML:
<input type="hidden" class="form-control" id="tags" ui-select2="modal.tags" data-placeholder="Available Tags" ng-model="form.tags">
JavaScript (Angular)
$scope.form = {tags: []};
postalTags = [
{
id: 1,
text: 'Permanent Address'
},
{
id: 2,
text: 'Present Address'
}
];
$scope.modal {
tags: {
'data': postalTags,
'multiple': true
}
};
// I doubt this is going to work, since i think this is only going to
// listen on events emitted by $emit and $broadcast.
$scope.$on('select2-removed', function(event) {
console.log(event);
});
// I can do this, but then i will not know which was removed and added
$scope.$watch('form.tags', function(data) {
console.log(data);
});
What the user actually is doing here is edit the tags tagged to his/her address, and by edit I mean the user can tag new tags to his/her address or remove previously tagged tags. That's why I need to track which tags where added and which are removed.
UPDATE
I saw a plausible solution on this discussion, but i cant make the provided code to work with mine, so i did some workaround, and this is what i did.
so instead of adding the,
scope.$emit('select2:change', a);
somewhere around here,
elm.select2(opts);
// Set initial value - I'm not sure about this but it seems to need to be there
elm.val(controller.$viewValue)
I put it here,
if (!isSelect) {
// Set the view and model value and update the angular template manually for the ajax/multiple select2.
elm.bind("change", function (e) {
// custom added.
scope.$emit('select2:change', e);
e.stopImmediatePropagation();
then i did the usual on my controller,
$scope.$on('select2:change', function(event, element) {
if(element.added) console.log(element.added);
if(element.removed) console.log(element.removed);
}
and works just fine.
But i doubt this is very good idea, and i'm still hoping for a better solution.
I used a directive to encapsulate the select and then in the link function I just retrieve the select element and at the event handler.
Markup:
<select name="id" data-ng-model="tagsSelection" ui-select2="select2Options">
<option value="{{user.id}}" data-ng-repeat="user in users">{{user.name}}</option>
</select>
Javascript:
link: function (scope, element, attributes) {
var select = element.find('select')[0];
$(select).on("change", function(evt) {
if (evt.added) {
// Do something
} else if (evt.removed) {
// Do something.
}
});
$scope.select2Options = {
multiple: true
}
}
I am using this https://github.com/blackgate/bg-splitter for creating horizontal and vertical pane splitters. (The full code is in the plunkr I have created)
Since I started using it, I have an issue with the two-way binding of a controller and directive.
The directive has two variables, listData and the selectedOption:
template: '<select ng-model="selectedOption" ng-options="l.name for l in listData" class="form-control"></select>',
scope: {
listData: "=",
selectedOption: "="
},
The controller has these variables and has a watch function to watch for changes:
$scope.listdata = [{id : 1, name : "listitem1"},{id : 2, name : "listitem2"},{id : 3, name : "listitem3"}];
$scope.selectedOption = null;
$scope.$watch('selectedOption', function() {
console.log('updating selected choice');
console.log($scope.selectedOption);
}, true);
And the directive is being used like:
<dropdown list-data="listdata" selected-option="listItem"></dropdown>
Without the paneSplitter the dropdown is working. For some reason, when the bound variable is updated in the dropdown directive, it doesn't get updated in the controller. This is probably a scope issue, but I can't seem to figure it out myself. Any help is greatly appreciated. Please see the following plunkr with the full code:
http://plnkr.co/edit/UnJaPV8LYm3unILEU3Lq
Remember the famous quote: "If you are not using a .(dot) in your models you are doing it wrong?"
If you change the watch to this:
$scope.$watch('data.listItem', function() {
console.log('updating selected choice');
console.log($scope.data.listItem);
}, true);
and in change the Html to this
<dropdown list-data="listdata" selected-option="data.listItem"></dropdown>
Here a Plunker
I am using AngularJS Modal Service. http://fundoo-solutions.github.io/angularjs-modal-service/
I setup it in a simple way
Button to open a Model
<div data-ng-controller="contest as vm">
<a class="btn btn-primary" data-ng-click="vm.createFileUploadDialog()">Upload Image</a>
</div>
Inisde Controller I have a function defined createFileUploadDialog and expose it from my viewModel.
vm.createFileUploadDialog = createFileUploadDialog;
vm.uploadme = {};
vm.uploadme.src = "";
function createFileUploadDialog() {
createDialog('/app/templates/fileuploadDialog.html', {
id: 'filuploadDialog',
title: 'Upload Contest Image',
backdrop: true,
success: { label: 'Upload', fn: uploadSuccess },
cancel: { label: 'Cancel' },
});
}
function uploadSuccess() {
console.log(vm.uploadme);
//need to call to the backend
}
And inside "fileUploadDialog.html" I have a simple markup
<div>
<input type="file" fileread="uploadme.src" />
</div>
"fileread" is a directive which return back the src of the File. Now the problem I have
As you can see I am doing console.log inside "UploadSuccess", in response I am getting the result "Object {src: ""}",
It looks like the Modal values not capture inside controller. But If I do the same with $rootScope, it logs out the File that need to upload. So, how can I access the value without using $rootScope? Please suggest
PS:
I am not define separate controller for Modal, want to use the same controller that treats my view.
** Modals scope is not the same as your controller scope!**
if you want to see your Controller scope inside of your modal and manupulate it , you're gonna have to use resolve inside of your modal markap like this :
createDialog('/app/templates/fileuploadDialog.html', {
id: 'filuploadDialog',
title: 'Upload Contest Image',
backdrop: true,
success: { label: 'Upload', fn: uploadSuccess },
cancel: { label: 'Cancel' },
resolve:{
controllerscope:function(){
return $scope;
}
}
});
And now , inside of your modal controller you can inject :** controllerscope ** and use it , also data binding works well like this :
app.controller('modalcontroller',function($scope,controllerscope){
// no you have access to your controller scope with **controllerscope**
})
So go and have a look at your modal plug in wich you are using and search for resolve and controller
thats it
I'm using Angular and Bootstrap.
I'm trying to replicate the functionality of ng-model for bootstrap checkbox. What i would like to accomplish is:
i would like that when i click on the checkbox (label really) the model change, and actually that works... but what does not work that when i try to watch the object for changes the behavior is weired, because i need two click insted of one for disable or enable the checkbox.
Moreover if inside the the label element that has as attribute cm-checkbox="model.prop" i put a {{model.anotherprop}} wont work (does not render anything).
From the documentation i understood that because i want the two-way data bind the scope must be defined as i did.
Thank you for your help!
I have the following HTML:
<label id="claim_free" class="checkbox" for="checkbox1" cm-checkbox="model.prop">
<span class="icons"><span class="first-icon fui-checkbox-unchecked"></span><span class="second-icon fui-checkbox-checked"></span></span><input name="claim_free" type="checkbox" value="" data-toggle="checkbox">
same lable text
</label>
And the following JS:
directive('cmCheckbox', function() {
return {
restrict: 'A',
scope: {'cmCheckbox':'='},
link: function(scope,elm,attrs) {
scope.$watch('cmCheckbox', function() {
console.log("first value for "+attrs.cmCheckbox+" is: "+scope.cmCheckbox);
if (!scope.cmCheckbox) {
console.log("checked");
$(elm).removeClass("checked");
$(elm).children("input").removeAttr("checked");
} else { // false and undefined
console.log("unchecked");
$(elm).addClass("checked");
$(elm).children("input").attr("checked","checked");
}
});
$(elm).on('click', function(e) {
e.preventDefault();
var currentValue = elm.hasClass("checked") ? false : true;
scope.$apply(function() {
scope.cmCheckbox = currentValue;
},true);
scope.$parent.$apply();
});
}
};
}).
Here is the jsFiddle: jsfiddle.net/pmcalabrese/66pCA/2