I'm currently trying to learn Angular and i have a list of products, and every product can be favorited which puts them in a menu called "Favorites" (What it really does is inserts a row in db, when clicked again it removes from db).
The functionality is done, i just want the button to have two "states" (when a product is favorited it should be yellow, and when its not favorited it should be transparent).
So somehow the link must check the controller which returns true or false depending on if the product exists in db, table: Part_Favorites.
CSS:
.active { background:yellow;}
.inactive { background:transparent;)
HTML:
<a ng-click="myfavorites()">Add favorites</a>
Controller
$scope.myfavorites = function (parts) {
CategoryService.myfavorites(parts, function (callback) {
//$route.reload();
window.location.reload(false);
});
if ($scope.loading == false) {
item.Checked == true ? item.Checked = false : item.Checked = true;
$scope.loopFilters();
$rootScope.loading = true;
$location.url('/Category/' + $routeParams.id + '/' + $scope.url);
}
};
Service:
myfavorites: function (data, callback) {
$http.post(shopID + '/Product/MyFavourites?SalesPartNo=' + data).success(function (data) {
callback(data)
}).error(function (data) {
callback(data);
});
},
EDIT: Updated my post with Service. Still need help!
The code works, and it inserts/deletes into a favorite menu. But how do i make it so it changes class on the button depending if its favorited or not?
<a ng-click="myfavorites()" ng-class="{active: item.Checked, inactive: !item.Checked}">Add favorites</a>
You can simplify the code a little bit:
item.Checked = !item.Checked;
item.className = item.Checked ? "active" : "inactive";
I believe you could print the class directly inside your template:
{{className}}
So it would just update it on the front end automatically.
You can use ng-class in here.
When you retriving the items get the favorite information too.
$scope.retrieveItems = function() {
//get the items with their favorite information(isFavorite [true,false])
}
Then in your html:
<a ng-click="myfavorites()" ng-class="{'active':item.isFavorite, 'inactive':!item.isFavoirte"/>
Related
I am trying to use Country/City dropdowns in multiple places of my project, however I am getting stuck with an unusual behaviour - when I am changing the countries. How can I make one request to get the local JSON file and populate multiple dropdowns?
Here is my code:
$(document).ready(function() {
fetch('assets/test.json').then(response => {return response.json()}).then(selectData => {
console.log(selectData)
function updateSelectsBirth() {
let citiesBirth = selectData[this.value].map((key, val) => {
return $("<option />").text(key).val(key);
});
$("#cityBirth, #cityBirth1").empty().append(citiesBirth);
}
let stateBirth;
$countryBirth = $("#countryBirth, #countryBirth1").on("change", updateSelectsBirth);
for (stateBirth in selectData) {
$("<option />").text(stateBirth).val(stateBirth).appendTo($countryBirth);
}
$countryBirth.change();
})
});
And the HTML
<select id="countryBirth"></select>
<select id="cityBirth"></select>
<br/>
<select id="countryBirth1"></select>
<select id="cityBirth1"></select>
Here's also a link to the demo project: link to the demo
The unexpected behaviour comes from
$("#cityBirth, #cityBirth1").empty().append(citiesBirth);
Because, when it's updating the cities, it's updating all the dropdowns instead of just one.
So you can try:
$(document).ready(function() {
fetch('assets/test.json').then(response => {return response.json()}).then(selectData => {
// console.log(selectData)
function updateSelectsBirth(event) {
let citiesBirth = selectData[this.value].map((key, val) => {
return $("<option />").text(key).val(key);
});
// console.log(event.data.target)
$(event.data.target).empty().append(citiesBirth);
}
let stateBirth;
$countryBirth = $("#countryBirth").on("change", {target: "#cityBirth"}, updateSelectsBirth);
$countryBirth1 = $("#countryBirth1").on("change", {target: "#cityBirth1"}, updateSelectsBirth);
// $countryBirth1 = $("#countryBirth1").on("change", updateSelectsBirth("#cityBirth1"));
for (stateBirth in selectData) {
$("<option />").text(stateBirth).val(stateBirth).appendTo($countryBirth);
$("<option />").text(stateBirth).val(stateBirth).appendTo($countryBirth1);
}
$countryBirth.change();
$countryBirth1.change();
})
});
I apologize this is not a complete answer, as I'm not generalizing to multiple dropdowns, however I am not able to leave comments yet. I hope this can still be helpful.
I have a requirement like saving two previous login details.
I am done with it. But my view will update only on refresh.But scope values are updated.
Tried with scope.apply,digest,timeout. But nothing seems to work here.
$scope.loginUserName=localStorage.getItem("loginUserName");
$scope.userName=localStorage.getItem("userName");
$scope.mobileNumber=localStorage.getItem("mobileNumber");
$scope.loginData = {};
$scope.userLogin = function(loginData) {
userService.userLogin(loginData).then(function(success) {
var res=success.message;
if(res==='success'){
if(localStorage.getItem("userName1")==null || localStorage.getItem("userName1") == success.firstName){
localStorage.setItem("userName1",success.firstName);
localStorage.setItem("loginUserName",success.firstName);
}else if(localStorage.getItem("userName2")==null || localStorage.getItem("userName2") == success.firstName ){
localStorage.setItem("userName2",success.firstName);
localStorage.setItem("loginUserName",success.firstName);
}
localStorage.setItem("userName",success.firstName);
$scope.userName=success.firstName;
$scope.mobileNumber = success.mobileNumber;
$scope.loginData = {};
$state.go('app.home');
}else{
$scope.message ='Wrong pin.Try again or click Forgot password to reset it.';
}
},function(error){
});
};
$scope.loginPerson = function(mobileNumber,userName){
localStorage.setItem("loginUserName",userName);
// here userName is updating,but not reflecting in view
$scope.loginUserName=localStorage.getItem("loginUserName");
//setTimeout(function(){ $scope.$apply(); });
console.log("In loginPerson:"+userName);
$state.go('app.start');
}
start.html
<span ng-if="loginUserName !=null">
<p class="startP">Enter pin for {{loginUserName}}
<i class="icon ion-chevron-down" ui-sref="app.loginOptions">
</i></p>
</span>
State
//Here is the state details,I have same controller for two state.
.state('app.loginOptions', {
url: '/loginOptions',
views: {
'menuContent': {
templateUrl: 'templates/loginOptions.html',
controller:'LoginCtrl'
}
}
})
.state('app.start',{
url:'/start',
views:{
'menuContent':{
templateUrl:'templates/start.html',
controller:'LoginCtrl'
}
}
EDIT
I have used within object also,But nothing is changed.
step 1) please use angular copy while get data from localstorage to $scope $scope.xyz=angular.copy(localstorage.get('key'))
after implement step 1 then not work use $scope.$apply(); after set value in $scope.
try to use loginUserName as a property of an object instead a property of scope directly. Sometimes angularjs fail to update view for these values.
Like
$scope.data={
loginUserName:""
};
Then inside your function
$scope.userLogin = function(loginData) {
...
$scope.data.loginUserName=localStorage.getItem("loginUserName");
// To check it
console.log($scope.data);
}
html
<span ng-if="data.loginUserName !=null">
...
</span>
Update
Change the loginPerson function like below.
$scope.loginPerson = function(mobileNumber,userName){
localStorage.setItem("loginUserName",userName);
$scope.data.loginUserName=localStorage.getItem("loginUserName");
console.log("In loginPerson:"+userName);
console.log($scope.data);
}
I recently took over the development of an AngularJS application created by my company, and am currently trying to add a button to a cell in a table, which the user will be able to use as a navigation button, and set the location it directs you to as any one of the user's custom pages.
In the table directive, I have added the following code:
.directive('appTable', function(fxTag) {
return {
...
template: '...',
controller: function($scope, $element, $compile, Global, fxEvent, fxSearch, NotifyMgr) {
...
var goToPageBtnTmpl = $compile(
'<a href="javascript:;" ng-click="goToPage(target)"' +
'<class="btn btn-xs btn-brand">Go to Page</a>'
);
console.log("goToPageBtnTmpl defined: ", goToPageBtnTmpl);
...
var goToPage = function(target) {
// Code to navigate to the page set by the user
console.log("goToPage button added: ");
};
...
}
}
})
and in ctrl.js, there is a toWidgetObj() function, which creates a widget based on the details that the user selects/ enters on a form:
}).controller('WidgetPickerCtrl', function($scope, $timeout, fxTag, gPresets, appWidget, appUI, pagesPresets) {
...
function toWidgetObj() {
...
var widgetObj = {
name: $scope.widget.name,
label: $scope.widget.label,
attr: angular.copy($scope.widget)
};
switch(widgetObj.name) {
case 'app-table':
...
angular.forEach(widgetObj.table.rows, function(row) {
if(row.length > 0) {
reducedRows.push(row.map(
function(tag) {
if(tag.isTag) {
return {tag: tag.tag, nounit: tag.nounit};
}
if(tag.isBtn) {
var goToPageBtnTmpl = $compile(
'Go to page'
)
}
}
));
}
});
...
break;
...
}
...
return widgetObj;
}
...
});
When I currently click the 'Edit widget' button on a table widget, the 'Edit Widget dialog is opened, and I add a button to a cell in the table. When I then click the 'Preview' button, to update the widget with the changes I have entered in the dialog, I see the print statement from the directive displayed:
goToPageBtnTmpl defined: publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){
assertArg(scope, 'scope');
and I am expecting the table to show a the button that has been compiled by the line:
var goToPageBtnTmpl = $compile(
'<a href="javascript:;" ng-click="goToPage(target)"' +
'class = "btn btn-xs btn-brand">Go to page</a>'
)
that will take the user to the page whose address I specified in the input on the dialog.
But what I actually see when I click 'Preview' is the table displayed, and the cell where the button should be displayed is actually showing the link that I typed (i.e. the address of the page I am expecting it to take the user to when clicked).
My debug in the console is stating that the button has been added successfully:
Tag is a button:
{tag: "pages/userpage1", isTag: false, isBtn: true, nounit: false, units: undefined}
isBtn
:
true
isTag
:
false
nounit
:
false
tag
:
"pages/userpage1"
units
:
undefined
but I don't actually see the button displayed on the page.
Anyone have any suggestions what I'm doing wrong here?
Edit
So, as I've looked into this further, I think I may have found the reason that the button is not displayed: the code where the button is compiled is written in the table directive's controller function:
.directive('appTable', function(fxTag) {
return {
...
controller: function(...) {
...
var gotToPageBtnTmpl = $compile(
...
);
So this is run when the page first loads. However, I am trying to add the button to the table manually, after the page has already loaded, and the code I'm using to do this is written later in the same controller function:
if(!$scope.noTagAlarm()) {
angular.forEach($scope.config.columns, function(col) {
...
if(col.header.startsWith(":")) {
angular.forEach($scope.config.rows, function(row) {
col.template = function(value, row, metadata) {
goToPageBtnTmpl(value);
}
})
}else{
console.log("column doesn't start with ':' ");
}
...
});
}
My thought is that since this code is written in the directive's controller function, it is probably only run when the page is first loaded, and not when I edit the widget using my 'edit widget' dialog, so the HTML is not rendered.
Would that be the case? If so, how can I reload the widget after editing it without refreshing the whole page? Or, if not, what am I actually doing wrong here?
The issue here was that the function used in the col.template needed to return the button I wanted to create:
col.template = function(value, row, metadata) {
return [
umWidget.getBtnTmpl(
$scope.$new(true),
goToPage,
value,
value)
];
}
I defined the getBtnTmpl() function in Widget/service.js with:
function getBtnTmpl(scope, fn, target, title) {
scope.fn = fn;
scope.target = target
var pageTitle = title.split('/');
scope.title = pageTitle[1];
return btnTmpl(scope);
}
and set btnTmpl as a global variable in Widget/service.js with:
var btnTmpl = $compile(
'<a href="javascript:;" ng-click="fn(target)"' +
'class="btn btn-xs btn-brand">{{title}}</a>'
);
I'm trying update a tinyint field called inactive from 0 to 1 whenever a button is clicked. I'm sure that I'm getting the correct id so there's no problem there but I can't update the field.
Here is my code for the view.
<a id="deactivate" role="button" href=<?php echo site_url('user/deactivate'); ?>>Deactivate</a>
<script>
$(document).ready(function() {
$('a#deactivate').bind('click',function(event){
if (confirm("Are you sure you want to deactivate " + id_deactivate + "?")) {
url_deactivate = ('<?php echo site_url('user/deactivate'); ?>');
$('a#deactivate').attr('href', function() {
var newURL0 = url_deactivate + "/" + id_deactivate;
console.log(newURL0);
return newURL0;
})
} else{
event.preventDefault()
}
});
});
</script>
for the model:
public function deactivateUser($id, $data){
if($this->db->update('user', "`inactive` = '".$data."'", "`user_id` = '".$id."'")){
return true;
}
return false;
}
And for the controller:
public function deactivate($id){
$this->session->set_userdata('page', 'user');
$this->session->set_userdata('action', 'view');
$data['inactive'] = 1;
$this->user_model->deactivateUser($id, $data);
redirect('user');
}
I'm pretty sure that the problem is with the controller but I don't know how to fix it. Can anyone help me? Thank you in advance.
in model try this
$this->db->where('user_id', $id);
$update = $this->db->update('user', $data);
if($update) return TRUE;
return FALSE:
See more info here
Instead of setting the href value after confirming the JS dialog (really weird way of going about it), just set the href already in the HTML.
Then you launch the JS confirm with
return (confirm("Are you sure you want to deactivate " + id_deactivate + "?")) ? true : false;
If you return true (when the user accepts the confirmation) you let the default action run its course, which is following the link in the href. If the user doesn't accept the confirmation you cancel the default action with a return false, and nothing happens.
I have an input type which uses angularjs type-ahead.The problem I am facing is that it disappears when I move my mouse over it. I am able to use the arrow keys to select items from the list,but am unable to click and select from the list.
I am getting list from the database,and the typeahead list is populating fine. Other places I used almost the same code,it works fine. When using this particular typeahead, after a while,say 5-6 trials, it behaves normally.
Any help will be appreciated.Thanks.
My html:
<input
id="{{roleAssignmentTableDTO.employeeNumberElementId}}" type="text"
name="employeeNumber"
ng-disabled="roleAssignmentTableDTO.disableEmployee"
ng-model="roleAssignmentTableDTO.employeeNumber"
typeahead="state for state in states | filter:$viewValue" />
My Controller:
$http
.post('rest/employeeSearch', query)
.success(
function(dataList) {
/*$scope.roleAssignmentDTO.roleAssignmentTableDTOList[elementId].searchLoader = false;
roleAssignmentTableDTO.showSearchLink=true;*/
if (dataList.length == 0) {
/*$scope.projectNotfoundError = true;
$scope.roleAssignmentDTO.roleAssignmentTableDTOList[elementId].showSearchLink = false;
$scope.projectNotfoundErrorMsg = 'You entered incorrect employee';*/
}
$.each(
dataList,
function(
i,
data) {
map[data.employeeNumber] = data;
List
.push(data.employeeNumber);
});
process(List);
})
.error(
function() {
$scope.roleAssignmentDTO.roleAssignmentTableDTOList[elementId].searchLoader = false;
$scope.projectNotfoundError = true;
$scope.projectNotfoundErrorMsg = 'Some Internal error occured';
List
.push("no data found");
process(List);
});
},
updater : function(selectedData) {
$scope.roleAssignmentDTO.roleAssignmentTableDTOList.employeeNumber = selectedData;
return selectedData;
}
});