I have a Laravel application and I want to add users an schools through wizards. I have made a very simple wizard with AngularJS.
$scope.addSchool = {
items : [ 1, 2, 3 ],
current : 1,
progress : 0
}
$scope.addSchoolNext = function(next)
{
$scope.addSchool.current = next;
$scope.addSchool.progress = (100 / $scope.addSchool.items.length) * ($scope.addSchool.current - 1);
}
$scope.addSchoolPrevious = function(previous)
{
$scope.addSchool.current = previous;
$scope.addSchool.progress = (100 / $scope.addSchool.items.length) * ($scope.addSchool.current - 1);
}
I have ng-switch in my view:
<div class="create-school-wizard" ng-switch on="addSchool.current">
<section class="create-school-wizard-1" ng-switch-when="1">
Add data
<button class="btn btn-default" ng-click="addSchoolNext(2)">Next</button>
</section>
<section class="create-school-wizard-2" ng-switch-when="2">
Add data
<button class="btn btn-default" ng-click="addSchoolPrevious(1)">Previous</button>
<button class="btn btn-default" ng-click="addSchoolNext(2)">Next</button>
</section>
<section class="create-school-wizard-3" ng-switch-when="3">
Add data
<button class="btn btn-default" ng-click="addSchoolPrevious(2)">Previous</button>
<button class="btn btn-default">Save</button>
</section>
</div>
It works fine! I have just one problem. When I go the the next page and then go back, the input fields are empty. Actually, I dont want to save my inputy data in AngularJS models because of, Laravel takes care for posting and saving the data.
I also tried ng-show, but ng-show submits the entire form when I click on next.
Since you didn't have a plunker, I created a different one. What happens when you go back and forth between pages, scopes get destoryed, so you need to repopulate the data when it loads.
Plunker link: http://plnkr.co/edit/laSUM6RDcF4SeTzMSCIu?p=preview
<div ng-switch on="someVariableToSwitchOn">
<div ng-switch-when="true">
<input ng-model="data.value" />
</div>
<div ng-switch-default>
<input ng-model="data.value" placeholder="Not prepopulated" ng-change="onChange()"/>
</div>
</div>
<input ng-model="data.prepopulated"/>
In this example you see that I can set the ng-model on an input and it will be tied to my scope variables.
My JS is a bit overly complex, but the basics are understandable. When the page loads I create $scope.data. it is not initialized so the first input will not switch. Once the user types "blue" into the first input, it will switch and do the other input will not run the change function.
If I want to prepopulate some input, then I have to do that as the page loads, so that it's done in a timely manner.
$scope.someVariableToSwitchOn = false;
$scope.data = {};
$scope.onChange = function(){
if($scope.data.value === 'blue'){
$scope.someVariableToSwitchOn = true;
console.log('switched');
} else {
$scope.someVariableToSwitchOn = false;
}
};
$scope.data.prepopulated = "prepopulated";
You can prepopulate these fields in a manner of ways, you can get data using $http from your server, or you can persist the data with localStorage in your browser (if you're just moving between pages and not relying on a server to save this (search for ng-localstorage) )
Related
I thought this should be something easy because I've done it before, but apparently the first time I got lucky, either that or Angular has some quirks I have not yet wrapped my head around.
What I'm trying to do is be able to edit a customer order. All customer orders are sent to the client from the database as JavaScript objects, using PHP.
That is fine, my problem is within Angular when I want to edit these orders, through a modal window (which has its own scope). Basically a form pops up in the modal that asks the user to edit the Javascript object, of course however no user wants to edit a raw object so it's a form with ng-models tied to that object. My problem is the ng-model doesn't seem to pick up my object reference.
So here we go (I have a plunker below):
This is the controller that fetches the customer order on the page the first time (before the user initiates the modal to edit the order):
controller: function($scope,$http,$stateParams,$uibModal) {
$http({
method: 'GET',
url: 'http://example.com/orderDATA',
params: {id: $stateParams.id}
}).then(function successCallback(html) {
html.data[0].orderProperties = JSON.parse(html.data[0].orderProperties); //format data from server so that JavaScript can play with it
$scope.order = html.data[0];
$scope.edit = function (order) //function that launches modal window
{
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'EditOrderInstance.html',
controller: 'EditOrderCtrl',
scope: $scope,
size: "lg",
resolve: {
order: function() {
return order;
}}
});
}
});
}
The edit() function is called like so from the following template:
<div class="container" style="margin-top:2%;">
<div class="row">
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy">Customer Name : #{{order.orderProperties.firstName + " " + order.orderProperties.lastName}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy">Pickup : #{{order.orderProperties.pickupDate + " in " + order.orderProperties.location}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy"><i class="fa fa-envelope" aria-hidden="true"></i> : #{{order.orderProperties.email}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<p class="whiteNoPointy"><i class="fa fa-phone" aria-hidden="true"></i> : #{{order.orderProperties.phone}}</p>
</div>
<div class="col-xs-12" style="text-align:center;">
<button type="button" style="border-radius:0;" class="btn btn-warning" ng-click="edit(order)">Edit This Order</button> <button type="button" style="border-radius:0;" class="btn btn-danger">Delete or Refund This Order</button> <button type="button" style="border-radius:0;" class="btn btn-primary">Complete This Order</button>
</div>
</div>
</br></br>
<div class="shipping whiteNoPointy text-center" ng-repeat="specific in order.order">
<div class="col-xs-12" ng-if="specific.quantity.value>0"><p>#{{specific.quantity.value}} #{{specific.Name}}</p></div>
</div></div>
This part works fine. However, when I do hit the edit function, that takes us into a new scope and a new controller, specifically the one below:
app.controller('EditOrderCtrl', ['$scope', '$http', '$uibModal','$uibModalInstance', 'order', function($scope, $http, $uibModal, $uibModalInstance, order) {
$scope.order = order;
So as is hopefully clear, all I did was pass the order object to the modal.
Now to me, all I've done is pass the same order object around, and now to this new controller. But the problem is that when I investigate this latest order it has no $$hashkey. I say this because of the problem that follows, as I said I did this before except in that instance I passed the order object from inside an ng-repeat, and the last step worked. But here when I do it it doesn't work.
What I mean is, when I try to have the models in the modal template line up with the order object passed to the modal's controller, they don't. I just get blank inputs, which isn't good because to edit a customer order you need to now what the current order is, otherwise it's like you are starting over.
Here is the template with the ng-model.
<script type="text/ng-template" id="EditOrderInstance.html">
<div class="modal-header" style="text-align:center;">
<h3 class="modal-title">Edit Order</h3>
</div>
<div class="modal-body" style="text-align:center;">
<form name="order" novalidate>
<label for="firstName">First Name</label>
<input type="text" name="firstName" class="form-control" ng-model="order.orderProperties.firstName" ng-minlength="2" required>
<p ng-show="orderorderProperties.firstName.$error.minlength" class="warning">Please put your full first name.</p>
</div>
<button ng-disabled="order.$invalid||totalPrice===0" ng-click="submitOrder()" class="btn btn-default">Submit</button>
</form>
</div>
<div class="modal-footer" style="text-align:center;">
<button class="btn toggledz" type="button" ng-click="save()">Submit</button>
<button class="btn" type="button" ng-click="cancel()">Cancel</button>
</div>
</script>
Notice the order.orderProperties.firstName ng-model. This is there, I console log it from the modal's controller and I can see it is set, but the model is blank. So why is this the case? Why did it work before when the console.log() showed the object was passed with a $$hashkey? I can't pass from an ng-repeat again because I only have one order, so there is nothing to iterate over in the first template.
Please assist. I need to be able to edit the order using ng-model, so that the admin can edit the order and send a new order object back to my server.
Edit: Added a plunker: https://plnkr.co/edit/x6FPiS6OtF2gdn4ZtFyJ?p=preview
From the first look, the problem appears to be with your resolve function
controller: function($scope,$http,$stateParams,$uibModal) {
$http({
method: 'GET',
url: 'http://example.com/orderDATA',
params: {id: $stateParams.id}
}).then(function successCallback(html) {
html.data[0].orderProperties = JSON.parse(html.data[0].orderProperties); //format data from server so that JavaScript can play with it
$scope.order = html.data[0];
$scope.edit = function (order) //function that launches modal window
{
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'EditOrderInstance.html',
controller: 'EditOrderCtrl',
scope: $scope,
size: "lg",
resolve: {
order: function() {
return $scope.order;
}}
});
}
});
}
Your resolve function for order should return $scope.order
Try it and let me know if this works. I am just going with the instincts
I got it to work by changing the variable name, I guess for some reason it was looking to the old $scope.order instead of the one resolved to the modal?
Anyway, here is a working plunker...
https://plnkr.co/edit/AZpeFGaBktFjSr2SL2Rv?p=preview
I want an alternative log in three type's user add, update, delete button show and hide, how is this possible in angularjs?
I'm trying to make the system as simple as possible.
HTML Code:
<div ng-show = "isOperator" class="panel-body">
<input ng-model="isoperator">
</div>
<div ng-show = "isAdmin" class="panel-body">
<input ng-model="isAdmin">
</div>
<div ng-show = "isSuper" class="panel-body">
<input ng-model="isSuper">
</div>
Javascript Code:
.controller("configCtrl" , ["$scope","$rootScope","$location","$http",
function($scope,$rootScope,$location, $http){
var operator = $scope.isOperator;
$scope.addConfigBtn=true;
$scope.addVpnConfigBtn=true;
$scope.canConfigBtn=true;
$scope.saveConfigBtn=true;
$scope.canVpnBtn=true;
$scope.savVpnBtn=true;
$scope.addUniBtn=true;
$scope.delUniBtn=true;
$scope.savUniBtn=true;
$scope.addNniBtn=true;
$scope.delNniBtn=true;
$scope.savNniBtn=true;
$scope.addRouteBtn=true;
$scope.delRouteBtn=true;
$scope.saveRouteBtn=true;
$scope.addLebRouteBtn=true;
$scope.delLebRouteBtn=true;
$scope.saveLebRoutebtn=true;
if(operator = $scope.isOperator){
$scope.isOperator=true;
$scope.addConfigBtn=false;
$scope.addVpnConfigBtn=false;
$scope.canConfigBtn=false;
$scope.saveConfigBtn=false;
$scope.canVpnBtn=false;
$scope.savVpnBtn=false;
$scope.addUniBtn=false;
$scope.delUniBtn=false;
$scope.savUniBtn=false;
$scope.addNniBtn=false;
$scope.delNniBtn=false;
$scope.savNniBtn=false;
$scope.addRouteBtn=false;
$scope.delRouteBtn=false;
$scope.saveRouteBtn=false;
$scope.addLebRouteBtn=false;
$scope.delLebRouteBtn=false;
$scope.saveLebRoutebtn=false;
}else{
$scope.isAdmin=false;
$scope.isSuper=false;
}
if($scope.isAdmin){
$scope.isAdmin=true;
$scope.addConfigBtn=true;
$scope.addVpnConfigBtn=true;
$scope.canConfigBtn=true;
$scope.saveConfigBtn=true;
$scope.canVpnBtn=true;
$scope.savVpnBtn=true;
$scope.addUniBtn=true;
$scope.delUniBtn=false;
$scope.savUniBtn=true;
$scope.addNniBtn=true;
$scope.delNniBtn=false;
$scope.savNniBtn=true;
$scope.addRouteBtn=true;
$scope.delRouteBtn=false;
$scope.saveRouteBtn=true;
$scope.addLebRouteBtn=true;
$scope.addLebRouteBtn=true;
$scope.delLebRouteBtn=false;
$scope.saveLebRoutebtn=true;
}
else{
$scope.isOperator=false;
$scope.isSuper=false;
}
if($scope.isSuper){
$scope.isSuper=true;
$scope.addConfigBtn=true;
$scope.addVpnConfigBtn=true;
$scope.canConfigBtn=true;
$scope.saveConfigBtn=true;
$scope.canVpnBtn=true;
$scope.savVpnBtn=true;
$scope.addUniBtn=true;
$scope.delUniBtn=true;
$scope.savUniBtn=true;
$scope.addNniBtn=true;
$scope.delNniBtn=true;
$scope.savNniBtn=true;
$scope.addRouteBtn=true;
$scope.delRouteBtn=true;
$scope.saveRouteBtn=true;
$scope.addLebRouteBtn=true;
$scope.addLebRouteBtn=true;
$scope.delLebRouteBtn=true;
$scope.saveLebRoutebtn=true;
}
else{
$scope.isOperator=false;
$scope.isAdmin=false;
}
In order to show or hide any HTML tag in angular, you can use directives ng-show and ng-hide.
e.g.
<input type="button" value="Save" ng-show="saveLebRoutebtn" />
Here, I used one of the variable defined in your $scope. On the basis of what you have in your $scope.saveLebRoutebtn, this control will shown on the HTML page. If the variable is not defined on the current $scope, it considers it to be false and hides the button.
To know more abot ng-show and ng-hide, follow this link
I'm listing my schedule entries, now I'm trying to display a modal when clicking on edit for a specific entry. My goal is to be able to edit the values of my entries. But first, can't get the modal to even display
See my plunker or code below
html
<div class="container" ng-app="appUserSchedule">
<div ng-controller="CtrlUserSchedule" >
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading">User Schedule</div>
<div class="panel-body">
<div ng-cloak style="max-width:400px;">
<header>
<h3>User schedule</h3>
</header>
<ul>
<li ng-repeat="x in userscheds">{{x.week_day}} {{x.time_start}}-{{x.time_end}}
<span ng-click="showModal($index)" style="cursor:pointer;">Edit</span>
<span ng-click="removeItem($index)" style="cursor:pointer;">Delete</span>
</li>
</ul>
<div>
<div>
<div>
<input placeholder="Add user schedule entry here" ng-model="addMe">
</div>
<div>
<button ng-click="addItem()">Add</button>
</div>
</div>
<p>{{errortext}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="modalContent.html" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Edit</h4>
</div>
<div class="modal-body">
<timepicker ng-model="dt1" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div> <!-- ng-controller -->
</div> <!-- ng-app -->
js
var app = angular.module("appUserSchedule", []);
app.controller("CtrlUserSchedule", function($scope,$http,$location) {
$http.get('userschedule.json').success(function(data, status, headers, config) {
$scope.userscheds = data.userschedules;
console.log(data);
}).error(function(data, status, headers, config) {
console.log("No data found..");
});
$scope.addItem = function () {
$scope.errortext = "";
if (!$scope.addMe) {return;}
if ($scope.userscheds.indexOf($scope.addMe) == -1) {
$scope.userscheds.push($scope.addMe);
} else {
$scope.errortext = "The item is already in your list.";
}
}
$scope.removeItem = function (x) {
$scope.errortext = "";
$scope.userscheds.splice(x, 1);
}
$scope.showModal = function (action, x) {
var modalInstance;
modalInstance = $modal.open({
templateUrl: 'modalContent.html',
controller: 'CtrlUserSchedule',
scope: $scope
});
// This code for later
// Save User Schedule Entry after making a change, then close modal
saveUserScheduleEntry = function(event) {
$http.put('').success(function(eventsuccess){
}).error(function(err){
/* do something with errors */
});
modalInstance.close();
};
// This code for later
// Close modal
closeUserScheduleEntry = function(event) {
$http.put('').success(function(eventsuccess){
}).error(function(err){
/* do something with errors */
});
modalInstance.close();
};
}
});
ng-repeat creates its own scope, hence the scope of your controller and the scope inside of the ng-repeat is not the same.
therefore $scope.showModal will not be defined inside of the ng-repeat.
the main mistake you are doing here is the "there always has to be a dot in there" rule.
look here:
Why don't the AngularJS docs use a dot in the model directive?
i would recommend to take a little tutorial about the most made angularjs mistakes first, because indeed there is some stuff to know about angularjs before you stop running into little traps like this.
furthermore you did not inject $modal to your controller which should lead in an error like $modal is undefined or something like that.
also you didn't even create/add the corresponding html file you are about to open.
and last but not least you didn't add any dependencies to your angular module regarding bootstrap. so your app won't be able to use/inject $modal anyhow.
see a working plunkr here:
http://plnkr.co/edit/rOjXt1C4E6lHRXUqHdHq?p=preview
have a look at the line where i am "putting the dot in"
$scope.ctrl = this;
i replaced the templateUrl by a simple template because i think it's enough to give the idea.
in the end i have to say that there was so many things wrong about your code that you really should try to debug more on your own and try to accomplish things more step by step.
since there have been like 4-5 mistakes in it this code barely can be your own, but rather is some random copy&paste stuff from anywhere.
otherwise you could not have accomplished that many different lines of code which don't do anything, sorry.
First is you need to add ui.bootstrap module to you ar angular app and pass $modal to your controller like this
var app = angular.module("appUserSchedule", ['ui.bootstrap']);
app.controller("CtrlUserSchedule", function($scope,$http,$location, $modal) {
Then you need to add modalContent.html. This displays the html inside modal window
This may not be the answer, but make sure showModal is receiving the correct arguments. Appears you are only sending $index.
Would have simply made this a comment, but not quite there on the reputation yet. :-)
I have a modal with a grid of buttons representing different html components. When one of the buttons is pressed, some html is supposed to be injected into the page once the modal closes. However, I'm having trouble targeting the specific column where the html is to be injected. Here's my code:
<div class="row" id="newRow">
<div class="col-md-12 column">
<button class="btn addElement" href="#" data-toggle="modal" data-target="#add-element"><i class="fa fa-plus fa-3x add-item"></i></button>
</div>
</div>
And in my js file I have some code to assign an id to the column div (since there could potentially be many columns with this addElement button) that looks like this:
...
$(this).parent().next().children().find('.column').assignId();
...
Up to this point, everything works well. I'm having no trouble getting the column a unique id (defined in my assignId() function).
As I mentioned, the addElement button gets clicked, opening a modal which is when this code is executed:
$(document).on('click', 'button.addElement', function (e) {
e.preventDefault();
$('#add-element').modal('show').draggable();
var col = $('button.addElement').parent();
// debugging in the browser verifies that the colId
// successfully stores the id attribute for the column
var colId = col.attr('id');
addElements(colId);
});
...
function addElements(colId) {
$('#insert-paragraph').on('click', function () {
var html_content = '<div class="box" data-type="paragraph">...</div>';
$("#newRow").find("#"+colId).html(html_content)
$('#add-element').modal('hide');
});
}
It's on this line: $("#newRow").find(colId).html(html_content); that I'm having the issue. My guess is that the formatting for find(...) is wrong and that I can't just insert a variable like that, but I've tried a few different things and nothing seems to be working.
Any help is very much appreciated.
Thanks!
UPDATE:
#juvian suggested writing a few of the variables' values to the console:
console.log(colId);
console.log($("#newRow")).length;
console.log($("#newRow").find("#"+colId).length);
console.log($("#newRow").find("#"+colId).html());
I logged these values twice. First, just before passing colId into the addElements function and in the addElements function immediately after $(#newRow").find("#"+colId).html(html_content); The results of those two tests are as follows:
Values prior to running addElements:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <button class="btn addElement"...>...</button>
Values after the insert-paragraph button is pressed:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <div class="box box-element" data-type="paragraph">...</div>
Interestingly enough, it appears like everything is working like I'd expect it to, however, when it's all said and done, the addElement button remains and the page still renders this:
<div id="newRow" class="row clearfix">
<div id="32aa-ab91-f50d-c3b3" class="col-md-12 column ui-sortable">
<button class="btn addElement" data-target="#add-element" data-toggle="modal" href="#">
<i class="fa fa-plus fa-3x add-item"></i>
</button>
</div>
</div>
.find as most jquery functions, takes a css selector as parametre. Unfortunately, colId is just a string, so it matches no elements (unless colId is html, span or something like that)
You are just missing adding the id selector at the beginning to do an id match:
.find("#"+colId)
I guess The parent of button is a div here which has no id.
var col = $('button.addElement').parent();
thus var colId is getting no value.give that div an id and it should be fine.
I have a list of Items with different button with them. Plunker
Quick View:
I want something like if I click on any of the buttons, related text will be copy to the div above. Also if I click on the button again it will removed from the Div.Same for each of the buttons. [I added manually one to show how it may display ]
I am not sure how to do that in Angular. Any help will be my life saver.
<div ng-repeat="item in csTagGrp">
<ul>
<li ng-repeat="value in item.csTags">
<div class="pull-left">
<button type="button" ng-class='{active: value.active && !value.old}' class="btn btn-default btn-xs">{{value.keys}}</button>
<span>=</span>
</div>
<div class="pull-left cs-tag-item-list">
<span>{{value.tags}}</span>
</div>
</li>
</ul>
</div>
The simplest thing would be to use $scope.tags object to store selected tags and add/remove them with the scope method similar to this:
$scope.tags = {};
$scope.toggleTag = function(tag) {
if (!$scope.tags[tag]) {
$scope.tags[tag] = true;
}
else {
delete $scope.tags[tag];
}
};
Demo: http://plnkr.co/edit/FrifyCrl0yP0T8l8XO4K?p=info
You can use ng-click to put in your scope the selected value, and then display this value instead of "Win".
http://plnkr.co/edit/IzwZFtRBfSiEcHGicc9l?p=preview
<div class="myboard">
<span>{{selected.tags}}</span>
</div>
...
<button type="button" ng-click="select(value)">{{value.keys}}</button>