I'm new with angular, I started nearly a week ago, but there are some features I don't quite understand yet... so be kind.
I wanted to bind in a ng-repeat some HEX codes (from icomoon for example), but suddenly the "fantastic" angular failed:
var app = angular.module("foooooods");
app.controller("foodController",['$scope','$http','$log',function($scope,$http,$log){
$scope.meals = [
{name:'colazione', id:1, font:""},
{name:'brunch', id:2, font:""},
{name:'pranzo', id:3, font:""},
{name:'snack', id:4, font:""},
{name:'cena', id:5, font:""},
{name:'dopo-cena', id:6, font:""}
];
...
now the html:
<div class="pasto" ng-repeat="(idmeal, meal) in meals">
<label title="{{meal.name}}" class="af-font">
{{meal.font}}
<input type="radio" value="1"
ng-model="fCtrl.tab"
ng-change="fCtrl.openNewMeal(idmeal)">
</label>
<p>{{meal.name}}</p>
</div>
what happened? <div class="pasto"> was de facto repeated, but {{meal.font}} was printed as plain text.
then I come up with a filter:
app.filter('trust', ['$sce',function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
}]);
but now I need to create an additional html element using the ng-bind-html, which I don't want... (if i don't use another element child in the <label> I loose its content) since the solution inline {{meal.font | trust}} inexplicably doesn't works.
<label title="{{meal.name}}">
<span class="af-font" ng-bind-html="meal.font | trust"></span>
<input type="radio" value="1"
ng-model="fCtrl.tab"
ng-change="fCtrl.openNewMeal(idmeal)">
</label>
help will be appreciated! THANKS.
NB - ng-bind-html-unsafe is deprecated.
I found out somewhere that unicode character are the solution. istead of an html entity write the unicode char:
//not working
{name:'colazione', id:1, font:""}
//perfectly working
{name:'colazione', id:1, font:"\ue900;"}
the secret is &#x<charcode> -> \u<charcode>. Maybe it will be helpfull for anyone looing for this simple achivement! bye
Related
How to modify so that we can use user input via empty fields on app rather than the current info...?
var dataObj = {
ID: "INFO226",
Name: "Application Development",
Overview: "An introduction to the use of software languages and tools for rapid application...",
Year: 2018,
Trimester: "1",
LectureTimes: "Thursday 12.40pm",
LecturerID: "1",
};
First of all, your question is not carrying the controller /html code snippet, so its really hard for me to understand what exactly you need here.
As per my assumption I am concluding your requirement and here is my answer to you..
Instead of var dataObj, use $scope.dataObj in controller.
In HTML,
<input type="text" ng-model="dataObj.ID" id="dataObjId"/>
<input type="text" ng-model="dataObj.Name" id="dataObjName"/>
<input type="text" ng-model="dataObj.Overview" id="dataObjOverview"/>
<input type="text" ng-model="dataObj.Year" id="dataObjYear"/>
and so on.
On submit of the form or on click of the Save button or so on your page, the dataObj scope is now modified with the user's input and can be submitted without pushing the data further.
My goal is to create in pure AngularJS a fill-in-the-blank activity which takes collection of records that contain phrases with markers where the blanks are, the correct answers, and incorrect answers to display along with them.
I've programmed a prototype in AngularJS/jQuery, below, which has the interactive functionality that I want, also here: http://jsfiddle.net/kkLdzngv/2/
What do I need to do to now is:
replace all the jQuery code with AngularJS code
make it dynamic so that not just one phrase is displayed, but all phrases in the collection are displayed with input fields each with the functionality that is in my prototype
In particular, I don't understand the correct AngularJS approach. I assume I need to use a ng-repeat to iterate through $scope.texts and inside the ng-repeat I would have my <div class="item">. But at that point, what functionality of AngularJS do I need to use to create the functionality shown in the prototype?
HTML:
<div class="item">
<div class="text">Customer 1 is from <input id="record_1_blank_1" ng-change="checkEntry_record_1_blank_1()" ng-model="record_1_blank_1"/> and Customer 2 is from <input id="record_1_blank_2" ng-model="record_1_blank_2"/>.</div>
<div class="answers">Munich, <span id="answer2">Berlin</span>, Frankfurt, Stuttgart, Hamburg</div>
</div>
JavaScript:
$scope.texts = [
{
body: 'Customer 1 is from [##blank] and Customer 2 is from [##blank].',
correctAnswers: 'Berlin;Hamburg',
incorrectAnswers: 'Stuttgart;Munich;Frankfurt'
},
{
body: 'Company 3 is located in [##blank].',
answers: 'Bremen'
}
];
$scope.checkEntry_record_1_blank_1 = function (obj) {
if ($scope.record_1_blank_1 == 'Berlin') {
$('#record_1_blank_1').css(
{
background: 'lightgreen'
})
.attr('disabled', 'disable');
$('#record_1_blank_2').focus();
$('#answer2').css('text-decoration', 'line-through');
}
};
I've got an angularjs application that has a form/controller that look essentially like this (boiled down to the pertinent stuff):
angular.module('testApp', [])
.controller('testCtrl', function ($scope) {
$scope.envelopes = [{
id: 1,
name: 'first',
default_spend: '1'
}, {
id: 2,
name: 'second',
default_spend: '0'
}, {
id: 3,
name: 'third',
default_spend: '0'
}, ];
});
And a form that looks roughly like this:
<div ng-app="testApp">
<div ng-controller="testCtrl">
<div ng-repeat="envelope in envelopes">
<div>{{envelope.name}}
<input type="radio" name="default_spend" ng-model="envelope.default_spend" ng-value="1" />
Default Spend: {{envelope.default_spend}}
</div>
</div>
</div>
</div>
You can see this in action with this fiddle.
As you can see, the first envelope is marked as the default_spend envelope and the other two aren't. When I select a different envelope, that envelope also gets marked as the default_spend, but when the radio button is unselected, the model value stays the same ("1"). I understand that I'm dealing with a child scope here due to ng-repeat, but is there a way for me to set an "unselected" value without having to jump through hoops with ngChange?
Not really. When you use ng-value it is what is going to get bound to the ng-model and in your case all of them are having value 1. Also i really did not get the purpose of toggling 1 and 0, however you could just achieve it this way:-
<input type="radio" name="default_spend"
ng-click="selected.envelope = envelope" /> <!--Register an ng-click and set selected one
Default Spend: {{getDefSpend(envelope)}}</div> <!-- Show the text based on selection-->
And in your controller:-
$scope.selected = {envelope: $scope.envelopes[0]};
$scope.getDefSpend = function(envelope){
return $scope.selected.envelope === envelope ? 1 : 0;
}
//$scope.selected.envelope will be your selected option at any point.
Demo
It's because what you have is actually 3 different model values. To work as you want it, you would have ONE model value for all 3. You can either restructure your data, or use ng-change to modify your model manually.
I'm new to Angular so please ELI5 if possible :)
I have a multiple-choice questionnaire with the setup for each question as below:
Question
Choice A
Choice B
Choice C
My controllers look like this:
scope.questionnaire = [
{
questionEN: "Thing?",
choice1EN: "Yes",
choice2EN: "No",
choice3EN: "Maybe",
questionPR: "Treasure?",
choice1PR: "Yarrr",
choice2PR: "Arrrrr",
choice3PR: "Parrrrley"
}
]
My current questionnaire looks like this:
<div ng-bind="questionnaire.questionEN"></div>
<input type="radio" name="{{questionnaire.questionEN}}" ng-model="questionnaire.choice" ng-value="questionnaire.choice1EN">{{questionnaire.choice1EN}}</input> <br />
<input type="radio" name="{{questionnaire.questionEN}}" ng-model="questionnaire.choice" ng-value="questionnaire.choice2EN">{{questionnaire.choice2EN}}</input> <br />
<input type="radio" name="{{questionnaire.questionEN}}" ng-model="questionnaire.choice" ng-value="questionnaire.choice3EN">{{questionnaire.choice3EN}}</input>
What I want to do is that at the start of the questionnaire, there are two buttons that will let the user select between languages.
[English] [Pirate]
So I have two questions, actually:
How do I do the language swapping without losing the user input (for example: they have answered questions 1-5 in [English], and while reading #6, scroll back up and hit the button to swap to [Pirate]. Their selected answers for 1-5 should remain, but all questions+choices have been "translated").
Is there a better way of arranging my controllers?
The answer to this really varies on your particular set of needs. Start with developing a logical model of the problem you are trying to solve.
Things to ask yourself:
Are the questions dynamic (loaded from a database) or static?
How do I need to store the answer? Can I store a choice ID, key, etc. or do I have to use the human readable value?
Does the model that captures the answers have to be different than the model that presents the question?
Do you need to store the language they selected along with the answers?
As you think about it more, other questions will follow.
Anyways, to give you something close to an answer here is a suggestion. If the questions are dynamic, you'll want to create a better structure for defining questions and the choices that are related to them. I'd also give them a key or ID so they can be referred to as concrete concepts. Not only does this help tie the model to database entries, making storing and retrieving easy, it makes it easier for you to handle the language issue.
Here's an example of such a design. You may wish to track the answers separately if your design requires, in my case I just kept it simple and kept the questions and answers in one model.
The question model is an array of objects that look like this:
{
key: 'q1', // unique key for question
text: { // a dictionary of language codes and the text of the question in that language
'en': 'What is the answer the question 1?',
'pr': 'Ahoy 1?'
},
choices: [{
key: 'q1a1', // a unique key for the choice
text: { // a dictionary of language codes and the text of the choice in that language
'en': 'Answer 1',
'pr': 'Arr 1'
}
}, {
key: 'q1a2',
text: {
'en': 'Answer 2',
'pr': 'Arr 2'
}
}],
value: null // the field that stores the user's selected choice
}
There is a helper function to get the language-specific text of the selected choice:
$scope.getAnswer = function(question) {
var answer = $filter('filter')(question.choices, {key: question.value});
if (answer.length == 1) return answer[0].text[$scope.selectedLanguage];
return '(no answer)';
};
The meat of your HTML template that displays the questions looks like this:
<div ng-repeat="question in model">
<label>{{question.text[selectedLanguage]}}</label>
<div>
<label ng-repeat="choice in question.choices">
<input type="radio" name="{{question.key}}" ng-value="choice.key" ng-model="question.value" />{{choice.text[selectedLanguage]}}
</label>
</div>
</div>
Alternative
For the heck of it, here's yet another example of how you might do it. This method is useful if you do not have dynamic question/choice data, but with some effort could still be used for dynamic data. It involves keeping localized UI strings in separate tables, assigning questions and choices unique keys, and then using a translation service to retrieve the correct string. In this example, I use the angular-translate module. I load it with tables of localization strings during .config of my module, specify a default language, and just use the translate filter when displaying questions and choices. This lets me greatly simplify my question model and get rid of some extra work in the views and controller.
My questions simply become:
{
key: 'q1',
choices: [
'q1a1',
'q1a2'
],
value: null
}
I add a watch on the language dropdown to change the current language:
$scope.$watch('selectedLanguage', function(value) {
if (value === null) return;
$translate.use(value);
});
And clean up the template:
<label>{{question.key | translate }}</label>
<div>
<label ng-repeat="choice in question.choices">
<input type="radio" name="{{question.key}}" ng-value="choice" ng-model="question.value" />{{ choice | translate }}
</label>
</div>
You could add a function using ng-click then set your $scope to a new questionnaire.
So you would have something like this:
var english = {
question: "Thing?",
answers: {
choice1: {text: "Yes", val: 1},
choice2: {text: "No", val: 2},
choice3: {text: "Maybe", val: 3}
}
}
var pirate= {
question: "Treasure?",
answers: {
choice1: {text: "Yarrr", val: 1},
choice2: {text: "Arrrrr", val: 2},
choice3: {text: "Parrrrley", val: 3}
}
}
// default
$scope.questionnaire = english;
$scope.choice;
// change language
$scope.changeLanguage = function (lang) {
switch (lang) {
case 0:
$scope.questionnaire = english;
break;
case 1:
$scope.questionnaire = pirate;
break;
}
}
Then for your buttons
<button ng-click="changeLanguage(0)">English</button>
<button ng-click="changeLanguage(1)">Pirate</button>
and finally, I would suggest using ng-repeat in your questionnaire
<div ng-bind="questionnaire.question"></div>
<label ng-repeat="answer in questionnaire.answers" ><input type="radio" name="{{questionnaire.question}}" ng-model="choice" ng-value="answer.val" />{{answer.text}} <br /></label>
i'm new to angular, stuck with, what i hope is a rather easy problem.
I Have a question and several answers. There might be 1-3 correct answers.
Answers can be selected by checkbox. In the value field i save if the answers is correct (true) or wrong (false). I was hopping that i can simply get things work by getting ng-valid and ng-invalid.
E.g. The answers is wrong, when clicked on the checkbox for this answer the anwswer text should be red (or sth.). When deselecting it should go back to normal. Same with correct answers.
That's how i currently try to do it:
<label ng-repeat="a in q.answers"><input type="checkbox" value="{{ a.correct }}" ng-pattern="true" ng-model="field.value"> {{ a.title }}</label>
So if the value is true it should match the pattern 'true'. Does not working, ng-pattern does not seem to have any effect.
Anyone know how to solve this.
If it's more sophisticated than i thought i might be doing the check with jquery. But i want to try pure angular first.
PS: i tried to find a answer to this, but i couldn't find anything that suits my problem.
Adding onto the class suggestion from Jared Reeves, here is one way that you might implement the checkbox answers:
<label ng-repeat="answer in question.answers" ng-class="{'invalid': answer.checked && !answer.correct, 'valid': answer.checked && answer.correct}">
<input type="checkbox" ng-change="select(field, answer)" ng-model="answer.checked"> {{answer.title}}
</label>
Selected answer: {{field.value}}
// inside the controller
$scope.field = {
value: null
};
$scope.question = {
answers: [
{title: "A (incorrect)", correct: false},
{title: "B (incorrect)", correct: false},
{title: "C (correct)", correct: true},
{title: "D (incorrect)", correct: false}
]
};
$scope.select = function(field, answer) {
if (answer.checked) {
field.value = answer;
} else {
field.value = null;
}
};
Here's a working example: http://plnkr.co/edit/Qa2VrukMD61y8Jv4iKjx?p=preview