I am creating a multi step form using AngularJS. I am not getting how to get the previous step. Flow of my form is two way. One can go from step 1 to step 4 via A way step1-->step2-->step3-->step4 and B way is step1-->step3-->step4.
I used <button class="SubmitPrev" ng-click="step = 1">Prev</button> code for getting the previous step. But when user is going by A way then previous step of step3 should be step2 and via B way the previous step of step3 should be step1. In step3, i can not use my previous button code because previous step of step3 depends on which way user is coming. I also tried to create alias of step3 but its increasing the number of lines as my form is consists of many steps with many ways. Is there any other way to call the previous step?
// Code goes here
var app = angular.module("MyApp", []);
app.controller('MyCtrl', function($scope, $timeout) {
$scope.name = '';
$scope.data = {
singleSelect: null,
multipleSelect: [],
option1: 'option-1',
};
$scope.forceUnknownOption = function() {
$scope.data.singleSelect = 'nonsense';
};
});
<!DOCTYPE html>
<html ng-app="MyApp" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body ng-controller="MyCtrl">
<form name='myform' id="myform" ng-init="step = 1" ng-submit="submitForm(myform.$valid)">
<div ng-show="step==1">
<h3>Which step</h3>
<div ng-form='step1form'>
<input type="radio" ng-disabled="!step1form.$valid" ng-click="step = 2"><p>Step 2</p>
<input type="radio" ng-disabled="!step1form.$valid" ng-click="step = 3"><p>Step 3</p>
</div>
</div>
<div ng-show="step==2">
<h3 class="zoomIn">which step</h3>
<div ng-form='step2form'>
<input type="radio" ng-disabled="!step2form.$valid" ng-click="step = 3"><p>Step 3</p>
<button class="SubmitPrev" ng-click="step = 1">Prev</button>
</div>
</div>
<div ng-show="step==3">
<h3 class="zoomIn">which step</h3>
<div ng-form='step3form'>
<input type="radio" ng-disabled="!step3form.$valid" ng-click="step = 4"><p>Step 4</p>
</div>
</div>
<div ng-show="step==4">
<h3 class="zoomIn">which step</h3>
<div ng-form='step4form'>
<p>Finish</p>
</div>
</div>
</form>
<script>document.write("<base href=\"" + document.location + "\" />");</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js"></script>
<script src="script.js"></script>
</body>
</html>
you can use: Angular Multi step form
multiStepForm is an angular module to create multi step forms and wizards. Create your steps like your would create your views with ngRoute or ui-router!
some of the main features:
Steps are controlled views and are easily configured
Isolated or non isolated scopes for steps
Track step validity if it contains a form
Store the current and previous step in your controller. So when clicking the previous button, set the current step to the previous step.
If that doesn't make sense, let me know and I'll provide a Plunker.
Here's a quick Plunker to demonstrate:
https://plnkr.co/edit/ofha6qAyNgJZj7XQ5Zk7?p=preview
Html:
<body ng-controller="MainCtrl as main">
<div ng-if="currentStep == 1">
<h1>Step 1</h1>
<button ng-click="setStep(2)">Go to step 2</button>
<button ng-click="setStep(3)">Jump to step 3</button>
</div>
<div ng-if="currentStep == 2">
<h1>Step 2</h1>
<button ng-click="setStep(3)">Go to step 3</button>
</div>
<div ng-if="currentStep == 3">
<h1>Step 3</h1>
</div>
<br>
<button ng-if="previousStep > 0" ng-click="setStep(previousStep)">Go to your previous step ({{previousStep}})</button>
<button ng-if="currentStep > 1" ng-click="setStep(currentStep - 1)">Go to {{currentStep - 1}}</button>
</body>
JS:
var app = angular.module('angularApp', []);
app.controller('MainCtrl', function($scope, $http) {
$scope.currentStep = 1;
$scope.previousStep = 0;
$scope.setStep = function(step) {
if (step == 1) { // If first step hide previous button
$scope.previousStep = 0;
} else {
$scope.previousStep = $scope.currentStep;
}
$scope.currentStep = step;
}
});
Related
I'm working to create not only a space for recent searches in local storage but also to create a new working button on my main project page once functioning. I am receiving an error message that the "addEventListener("click", buttonClickHandler); call I have at the very bottom of my code cannot read property of "null" so I'm wondering where I went wrong in the starting piece. I have tried to rework this piece of JS so many times now and I'm just not sure where to go from here at this point. Any advice?
var cityFormEl = document.querySelector("#city");
var cityNameInputEl = document.querySelector("#location");
var dateFormEl = document.querySelector("#date");
var dateNameInputEl = document.querySelector("#today");
var historyButtonsEl = document.querySelector("#search-item");
var historyCardEl = document.querySelector("#recent-searches");
var trashEl = document.querySelector("#trash");
var searchHistoryArray = []
var formSubmitHandler = function (event) {
event.preventDefault();
// get city name value from input element
var cityBtn = cityNameInputEl.value.trim();
// Set city name in local storage and generate history buttons
if (cityBtn) {
searchHistoryArray.push(cityBtn);
localStorage.setItem("citySearch", JSON.stringify(searchHistoryArray));
localStorage.setItem("dateSearch", JSON.stringify(searchHistoryArray));
var searchHistoryEl = document.createElement('button');
searchHistoryEl.className = "btn";
searchHistoryEl.setAttribute("data-city", "data-date", cityBtn)
searchHistoryEl.innerHTML = cityBtn;
historyButtonsEl.appendChild(searchHistoryEl);
historyCardEl.removeAttribute("style")
cityNameInputEl.value = "";
}
else {
alert("Please enter a Date and a City name");
}
}
// Load any past city searches
var loadHistory = function () {
searchArray = JSON.parse(localStorage.getItem("citySearch"));
if (searchArray) {
searchHistoryArray = JSON.parse(localStorage.getItem("citySearch", "dateSearch"));
for (let i = 0; i < searchArray.length; i++) {
var searchHistoryEl = document.createElement('button');
searchHistoryEl.className = "btn";
searchHistoryEl.setAttribute("data-city", "data-date", searchArray[i])
searchHistoryEl.innerHTML = searchArray[i];
historyButtonsEl.appendChild(searchHistoryEl);
historyCardEl.removeAttribute("style");
}
}
}
// Search using search history buttons
var buttonClickHandler = function (event) {
var cityBtn = event.target.getAttribute("data-city", "data-date",);
if (cityBtn) {
formSubmitHandler(cityBtn);
}
}
// Clear Search History
var clearHistory = function (event) {
localStorage.removeItem("citySearch", "dateSearch");
historyCardEl.setAttribute("style", "display: none");
}
cityFormEl.addEventListener("submit", formSubmitHandler);
historyButtonsEl.addEventListener("click", buttonClickHandler);
trashEl.addEventListener("click", clearHistory);
loadHistory();
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Adventure Time</title>
<link rel="stylesheet" href="../adventure-time/assets/css/styles.css" />
<link rel="stylesheet" href="../adventure-time/build/styles.css" />
</head>
<body>
<header>
<nav class="flex justify-between items-center">
<a href="#"><img class="max-w-xs p-8" src="../adventure-time/assets/img/adventure-time-logo-reverse.png"
alt="Logo of Adventure Time" /></a>
Recent Searches
</nav>
<section class="hero">
<div class="hero-statement">
<h2>
Your <span id="adventure"> Adventure</span> <br />
Starts here
</h2>
<p>Enter a time and place to start your journey</p>
<br />
</div>
<form class="search-input flex justify-between">
<div id="date">
<input type="date" id="today" name="date" value="2021-08-01" min="2021-08-01" max="2022-12-31"
class="date-input cst-btn cst-btn-lft">
</div>
<div class="time-input cst-btn cst-btn-cntr"><input type="time" id="time" name="time" min="07:00"
max="22:00" required></div>
<div class="location-input cst-btn cst-btn-cntr">
<div id="city">
<label>City</label>
<input id="location" type="text" tabindex="3" name="city">
</div>
</div>
<button class="cst-btn cst-btn-rgt" id="search"><a href=adventure.html>Find my Adventure</a></button>
</form>
</section>
<!-- HERO END -->
</header>
<main class="m-auto w-3/4">
<div id="recent-searches">
<h2 class="text-black text-4xl text-center">Recent Searches</h2>
<div class="recent-searches flex justify-around">
<div class="search-item">
<h4>Los Angeles, CA</h4>
<p>Sat, Jul 7 at 3:00 PM</p>
</div>
<div class="search-item">
<h4>Portland, OR</h4>
<p>Sat, Jul 7 at 3:00 PM</p>
</div>
<div class="search-item">
<h4>New York, NY</h4>
<p>Sat, Jul 7 at 3:00 PM</p>
</div>
<div class="search-item">
<h4>Vancouver, BC</h4>
<p>Sat, Jul 7 at 3:00 PM</p>
</div>
</div>
</div>
</div>
</main>
<footer class="main-footer">
<h5>Made with ❤️  by Team Awesome</h5>
</footer>
<script src="../adventure-time/assets/js/script.js"></script>
</body>
</html>
I ran your code and got this error (although I am not entirely sure if this is what you are referencing):
Uncaught TypeError: historyButtonsEl is null
The reason this TypeError is being thrown lies in this line of your JS:
var historyButtonsEl = document.querySelector("#search-item");
You are selecting for an element that has an ID equal to 'search-item'; however, the only reference to 'search-item' in your html is a class. To fix this, simply do:
var historyButtonsEl = document.querySelector(".search-item");
Notice the '.' instead of a '#'. '#' select ids whereas '.' select classes. Also, although I am unsure what you are trying to select with this querySelector(), I ought to warn you that selecting classes with querySelector() will return the first found element with that class and not all elements with that class (to do that use querySelectorAll()). Hopefully this helped.
I'm building a calculator, and while it's starting to work, I'm kind of stuck. I've pasted the HTML and the JS down here.
I've been trying to figure out what went wrong, and I think it's because of the functions calling each other and not properly... "closing/ending". I've been trying to see what went wrong with adding console.logs. I'll break it down here:
I press "on" and function listenFirst gets run.
listenFirst has an eventListener and waits for the user to click a number (firstNumber). As soon as a number is clicked, waitforOperator is run (which now has the firstNumberas an attribute. Now,
waitforOperator waits for a click on the plus sign, and as soon as the user clicks on the plus sign, listenSecondgets run. Now this is where it
goes wrong: as soon as I click the second number, waitforOperatorgets run again and now firstNumber and secondNumber are the same.
To be clear: I just want this problem solved before I delve into the other operators, so please don't pay attention to the other operators like minus and multiplication.
A nudge in the right direction would be nice! Thanks in advance.
let displayBox = document.getElementById("displayBox");
let pressButton = document.querySelectorAll(".column");
let turnOn = document.getElementById("turnOn");
let minus = document.getElementById("minus");
let plus = document.getElementById("plus");
let firstNumber = Number();
let secondNumber = Number();
turnOn.addEventListener("click", function() {
displayBox.textContent = "CALCULATOR ON. GIVE FIRST NR.";
console.log("launching function listenFirst");
listenFirst();
});
let listenFirst = () => {
console.log("launched listenFirst");
for (var i = 0; i < pressButton.length; i++) {
pressButton[i].addEventListener("click", function() {
firstNumber = displayBox.textContent = Number(this.id);
waitForOperator(firstNumber);
});
}
};
let listenSecond = () => {
console.log("launched listenSecond");
console.log(`first number is still ${firstNumber}`)
console.log(`waiting for you to press second number`)
for (var i = 0; i < pressButton.length; i++) {
pressButton[i].addEventListener("click", function() {
secondNumber = displayBox.textContent = Number(this.id);
console.log(`After click on second number, first number is ${firstNumber} and second number is ${secondNumber}`)
});
}
console.log(
`Now first number is ${firstNumber} and second number is ${secondNumber}`
);
};
let waitForOperator = () => {
console.log("launched waitForOperator");
console.log(`First number is ${firstNumber}`);
console.log("Waiting for you to press plus");
plus.addEventListener("click", function() {
listenSecond(firstNumber);
});
};
let calculateSum = () => {
console.log(`Second number is ${secondNumber}`);
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hello Bulma!</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css"
/>
<script
defer
src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"
></script>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<section class="section">
<h1 class="title has-text-centered" id="titleText">Calculator.</h1>
<div class="container">
<div class="field">
<a class="button is-fullwidth is-static" id="displayBox"></a><a class="button is-success" id="turnOn">ON</a>
</div>
<div class="calculator">
<div class="columns">
<div class="column" id="7">7</div>
<div class="column" id="8">8</div>
<div class="column" id="9">9</div>
<div class="column" id="minus">-</div>
</div>
<div class="columns">
<div class="column" id="4">4</div>
<div class="column" id="5">5</div>
<div class="column" id="6">6</div>
<div id="plus">+</div>
</div>
<div class="columns">
<div class="column" id="1">1</div>
<div class="column" id="2">2</div>
<div class="column" id="3">3</div>
<div class="column" id="equals">=</div>
</div>
<div class="columns">
<div class="column" id="0">0</div>
<div class="column" id="dot">.</div>
</div>
</div>
</div>
</section>
<script src="script.js"></script>
</body>
</html>
You never remove the event listener you added to number number buttons in listenFirst. So when the user presses the buttons after waitForOperator both the code in listenFirst and listenSecond runs. listenFirst call waitForOperator again.
JavaScript: remove event listener Have a look at this answer for how to remove event listeners.
I have set of four button and I want to make them toggle and active on click of the button. Currently my buttons are get toggled on double click.
The solution what I am expecting is, when I click on the button current btn should get highlighted and data should be displayed and when I click on the next button, previous content should get hidden and current content should be visible.
Code:
(function() {
var app = angular.module('myapp', []);
app.controller('toggle', function($scope) {
$scope.Ishide_bank = true;
$scope.bank = function() {
$scope.Ishide_bank = $scope.Ishide_bank ? false : true;
};
$scope.Ishide_asset = true;
$scope.assets = function() {
$scope.Ishide_asset = $scope.Ishide_asset ? false : true;
};
$scope.Ishide_address = true;
$scope.address = function() {
$scope.Ishide_address = $scope.Ishide_address ? false : true;
};
$scope.Ishide_personal = true;
$scope.personal = function() {
$scope.Ishide_personal = $scope.Ishide_personal ? false : true;
};
});
})();
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body ng-controller="toggle">
<div>
<button class="bttn" ng-click="address()">Address</button>
<button class="bttn" ng-click="personal()">Personal-details</button>
<button class="bttn" ng-click="bank()">Bank-Account</button>
<button class="bttn" ng-click="assets()">Asset</button>
</div>
<div ng-hide="Ishide_address">
<h1>Btn 1</h1>
</div>
<div ng-hide="Ishide_bank">
<h1>Btn 2</h1>
</div>
<div ng-hide="Ishide_asset">
<h1>Btn 3</h1>
</div>
<div ng-hide="Ishide_personal">
<h1>Btn 4</h1>
</div>
</body>
</html>
Plunker : https://plnkr.co/edit/8hr9zXXkgBkBZRqUjpks?p=preview
Please let me know where I am going wrong.
first of your script order is wrong!
angular lib should be first then custom script.js
also below is the simplest way to do what you trying to do.
(function() {
var app = angular.module('myapp', []);
app.controller('toggle', function($scope) {
$scope.view = 'default';
$scope.toggle_view = function(view) {
$scope.view = $scope.view === view ? 'default' : view;
};
});
})();
.bttn {
background: #eee;
border: 1px solid #aaa;
}
.bttn.active {
background: yellow;
}
.bttn:focus {
outline: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<div ng-controller="toggle">
<div>
<button class="bttn" ng-class="{'active': view === 'address'}" ng-click="toggle_view('address')">Address</button>
<button class="bttn" ng-class="{'active': view === 'personal'}" ng-click="toggle_view('personal')">Personal-details</button>
<button class="bttn" ng-class="{'active': view === 'bank'}" ng-click="toggle_view('bank')">Bank-Account</button>
<button class="bttn" ng-class="{'active': view === 'asset'}" ng-click="toggle_view('asset')">Asset</button>
</div>
<div ng-show="view === 'address'">
<h1>Address View</h1>
</div>
<div ng-show="view === 'bank'">
<h1>Bank View</h1>
</div>
<div ng-show="view === 'asset'">
<h1>Asset View</h1>
</div>
<div ng-show="view === 'personal'">
<h1>Personal View</h1>
</div>
</div>
</div>
In my Single Page App, specifically in the javascript file I am getting an error for uncaught reference for the reroll function. I do not understand what is causing this issue. Is my js file setup the wrong way?
The specific error stated is, Reference Error, reroll is not defined.
HTML:
<body ng-app="app">
<!-- == Main Controller for SPA == -->
<div class="container-fluid bg-dark text-white" style="height:700px" ng-controller="mainCtrl">
<!-- == App Title == -->
<h2 class="display-2 title-container text-center">{{main.title}}</h2>
<div class="row">
<div class="container-fluid word-container text-center">
<!-- == User Phrase Input == -->
<input type="text" ng-model="word" placeholder="Please enter word">
<br>
<br>
</div>
</div>
<div class="row">
<div class="container-fluid anagram-container text-center">
<!-- == Final anagram == -->
Anagram: {{anagram}}
</div>
</div>
<div class="row">
<div class="container-fluid button-container text-center">
<!-- Anagram "Reroll" Button -->
<button type="button" ng-click="reroll(word)" class="btn btn-primary btn-large">Reroll</button>
<!-- Anagram "Clear" Button -->
<button type="button" class="btn btn-primary btn-large" ng-click="word=''">Clear</button>
</div>
</div>
</div>
</body>
Javascript:
var app = angular.module("app", []);
app.controller('mainCtrl', function($scope) {
$scope.main = {};
$scope.main.title = "AnagramJS";
$scope.reroll = function reroll(value) {
// set anagram to randomize
$scope.anagram = value.split('').sort(function() {
return 0.5 - Math.random()
}).join('');
};
$scope.$watch('word', (newVal, oldVal) => {
if (newVal) {
reroll(newVal);
} else {
// empty anagram if word is empty
$scope.anagram = "";
}
});
angular.extend($scope, {
reroll
});
});
reroll(newVal) should be $scope.reroll(newVal);
Also remove the
angular.extend($scope, {
reroll
});
So I want the user coming to my portfolio to enter their first name on the index.html page. Then I will welcome the user on the welcome page. How do I pass the information from the index.html to the welcome.html. I'm a novice at angular, your will be very grateful!
index.html:
<header ng-controller="UserName as myApp">
<form >
<label><h1>Enter Your First Name: </h1></label>
<input type="text" ng-model="user.name" name="clients" autofocus />
<button>CLICKME</button>
</form>
<h1>{{user.name}}</h1>
</header>
welcome.html:
<div class="container">
<div class="propic"></div>
<div class="blurb">sfdvsdfvsdv <span ng-controller="FirstCtrl">{{data.message}}</span> fsdv sdfvsdfv sdf fs vsdfv sdfvf f vsdfv sdfv sfdv dsv fdv</div>
</div>
app.js:
(function(){
var myApp = angular.module('myApp', []);
myApp.controller('UserName', function(){
this.product = name;
});
var User = {
name: ""
}
});
Here is the github: https://github.com/wiafe/Portfolio
And here is the page: http://wiafe.github.io/Portfolio/
PS: The h1 that's being bind in index.html can be ignored I was just testing something.