Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
WORLDS BEST BABY
Aug 26, 2006

This is a bit Webpack/React specific, but I've been using CSS Modules with Webpack's css-loader. The two biggest features of this (to me) are: 1) locally scoped styles 2) composable styles. I've been using it a lot this week and being able to write styles without even having to think twice how it might conflict with styles someplace else is just magic, as well as being able to make CSS classes that are as composable as, well, React components. I really feel like something like this is where styling for the web is headed in the long term.

Being able to use Sass on top of that is just the cherry on top (and really highlights how great Webpack is).

Adbot
ADBOT LOVES YOU

Heisenberg1276
Apr 13, 2007
I already use SCSS. I was thinking more in the way the CSS is structured. CSS Modules looks like the right sort of thing! thanks

uXs
May 3, 2005

Mark it zero!
Angular (1.4) question:

Say I have a page with a menu on top and content below. They each have their own controller. (Not nested.)

Sometimes the content is a form where users can edit some things. The 'save changes' button for this should appear in the menu bar. Said button should somehow call the save() method of the content controller. Any ideas on how best to do this?

I tried it with broadcast but couldn't get it work yet. (Because I was operating under the assumption that the content controller was nested in the menu controller.) But even if/when I get that to work, I feel that broadcasting/and or emitting events isn't the best way to achieve this anyway.

Would using some kind of service be a good idea? The service would be injected in both menu and content controller, and the menu controller would call poo poo on the service and the content controller can react to it. Or is that stupid? Or is the entire setup stupid?

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me

uXs posted:

Angular (1.4) question:

Say I have a page with a menu on top and content below. They each have their own controller. (Not nested.)

Sometimes the content is a form where users can edit some things. The 'save changes' button for this should appear in the menu bar. Said button should somehow call the save() method of the content controller. Any ideas on how best to do this?

I tried it with broadcast but couldn't get it work yet. (Because I was operating under the assumption that the content controller was nested in the menu controller.) But even if/when I get that to work, I feel that broadcasting/and or emitting events isn't the best way to achieve this anyway.

Would using some kind of service be a good idea? The service would be injected in both menu and content controller, and the menu controller would call poo poo on the service and the content controller can react to it. Or is that stupid? Or is the entire setup stupid?

If you have a central service which your main controller saves all it's data to all the time, and the menu controller then is the one which calls 'save'(which sends to DB) on the service, this will work, but it really depends on your application particulars how well.

A few other ways.

1. Broadcast/emit will work. You need to either emit up to the $rootScope, then broadcast back down, or include $rootScope in your menu controller and broadcast straight down from it.

2. Use a pub/sub message bus library like Amplify or Postal to talk between controllers. This is functionally the same as broadcast/emit, but it's a lot easier to abstract away into a service with your own syntax. I would suggest this route.

3. Don't do this, but you CAN grab references to other controllers with the $controller service. You can then have one controller directly call another controllers methods. But this is a bad idea and you shouldn't do it.

Edit: I made a post a few pages back about doing #2 with Typescript for strongly typing such a message bus service, if interested.

Skandranon fucked around with this message at 15:44 on Jun 26, 2015

uXs
May 3, 2005

Mark it zero!
I did it with this:

code:
angular.module('myApp').service('saveClickingService', [
  function () {
      var listeners = [];
      return {
          click: function (args) {
              listeners.forEach(function (cb) {
                  cb(args);
              });
          },
          register: function (callback) {
              listeners.push(callback);
          },
          unregister: function(callback) {
              listeners.pop(callback);
          }
      };
  }
]);
and this:

code:
    angular
        .module('myApp')
        .controller('ProjectAddController', ProjectAddController);

    //ADD
    ProjectAddController.$inject = ['$scope', '$location', 'Project', 'saveClickingService'];

    function ProjectAddController($scope, $location, Project, saveClickingService) {
        $scope.project = new Project();
        $scope.add = function () {
            $scope.project.$save(function () {
                $location.path('/projecten');
            });
        }

        saveClickingService.register(addCallBack);

        function addCallBack() {
            $scope.add();
        }

        $scope.$on('$destroy', function () {
            saveClickingService.unregister(addCallBack);
        });
    }
and this

code:
    angular
        .module('myApp')
        .directive('onSaveClick', onSaveClick);

    onSaveClick.$inject = ['saveClickingService'];

    function onSaveClick(saveClickingService) {
        return {
            restrict: 'A',
            link: function (scope, element) {
                element.on('click', saveClickingService.click);
            }
        };
    };
First block of code is a service where things that are interested in the save clicks can register their callbacks.

Second is the controller with the save() function, that registers a callback to it with the service. (And removes it on destroy.)

And third is where I define the directive. I can use it by putting 'on-save-click=""' on a hyperlink tag.

I like it, it looks clean.

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me

uXs posted:

I did it with this:

First block of code is a service where things that are interested in the save clicks can register their callbacks.

Second is the controller with the save() function, that registers a callback to it with the service. (And removes it on destroy.)

And third is where I define the directive. I can use it by putting 'on-save-click=""' on a hyperlink tag.

I like it, it looks clean.

This is basically #2, except you wrote your own version of AmplifyJS, that only handles one type of event. If you plan to scale beyond this one use case, I'd suggest using Amplify, and use your Angular service to wrap around it.

Also, use BindToController & ControllerAs in your directives, and don't use $scope anymore for your functions or variables, will make things even cleaner.

uXs
May 3, 2005

Mark it zero!

Skandranon posted:

This is basically #2, except you wrote your own version of AmplifyJS, that only handles one type of event. If you plan to scale beyond this one use case, I'd suggest using Amplify, and use your Angular service to wrap around it.

Also, use BindToController & ControllerAs in your directives, and don't use $scope anymore for your functions or variables, will make things even cleaner.

Ok cool, thanks, I'll try all of that.

Heskie
Aug 10, 2002

Heisenberg1276 posted:

I already use SCSS. I was thinking more in the way the CSS is structured. CSS Modules looks like the right sort of thing! thanks

Take a look at Harry Robert's inuitcss.

You build your own modular CSS on top of his experience. I've found it to be very good. Google his CSS guidelines also.

Things like Compass and Bourbon are near obsolete nowadays in my opinion due to Autoprefixr handling vendor prefixes which seemed to make up the majority of the mixins provided.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
Yeah. Don't use Mixin libraries for prefixing, it's a poor use of what you should be using mixins/extends for, reusing patterns and design constructs specific to your project.

an skeleton
Apr 23, 2012

scowls @ u
I have an angularjs directive that has some scope functions and some parser/formatter functions. It seems the ctrl (4th parameter of the linking function) object is different in the scoped functions than in the parser functions. what gives? here's a rough example

code:
link function(a, b, c,  ctrl){

 scope.blarg = function(){
   console.log(ctrl[0]);
 }

 modelCtrl.$parser.unshift(function(){
  console.log(ctrl[0]); //value will be different
 });

}

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me

an skeleton posted:

I have an angularjs directive that has some scope functions and some parser/formatter functions. It seems the ctrl (4th parameter of the linking function) object is different in the scoped functions than in the parser functions. what gives? here's a rough example

code:
link function(a, b, c,  ctrl){

 scope.blarg = function(){
   console.log(ctrl[0]);
 }

 modelCtrl.$parser.unshift(function(){
  console.log(ctrl[0]); //value will be different
 });

}


I'm not sure what you are asking, so I'll just give a run down of how link functions work and maybe hit what you are looking for. To start, your link functions should be named better. The first three parameters are supposed to be "scope, element, attrs", as they are populated with the directives $scope, the element the directive is attached to, and an array of HTML attributes on that element. The fourth parameter is optional, which can either be a single Controller, or an array of Controllers. This is determined by the directive definition "require" field. If multiple directives are listed here, the controllers from all of them will be included as an array. If nothing is specified, the controller specified for that directive will be there (if there is one).

Also, it's pretty bad practice to be adding functions to the scope in the link function. If you want to add functions to the scope that the template or controller is going to call, put it in the Controller. The link function should only be about manipulating DOM elements (using jQuery and such). For that matter, use bindToController and controllerAs in your directive, and keep your functions in the Controller object altogether.

Skandranon fucked around with this message at 18:15 on Jun 30, 2015

WORLDS BEST BABY
Aug 26, 2006

ReactEurope are streaming their conference, if that interests you. There'll probably be a few interesting updates on new projects (crossing my fingers for Relay) on top of everything else:

https://www.youtube.com/watch?v=UclvvqNtNNo

Kekekela
Oct 28, 2004

WORLDS BEST BABY posted:

ReactEurope are streaming their conference, if that interests you. There'll probably be a few interesting updates on new projects (crossing my fingers for Relay) on top of everything else:

https://www.youtube.com/watch?v=UclvvqNtNNo

Thanks, this is great!

e: Very cool thing referenced in stream: Dan Abramov's React List

Kekekela fucked around with this message at 11:22 on Jul 2, 2015

White Light
Dec 19, 2012

Got a simple question about Sublime that i'm hoping you fellas could answer for me!

I recently installed the Emmet package in Sublime to help speed up my work flow, but for some reason I can't seem to get the most basic keystroke shortcut to work for me. It's the simple one where you type "!" followed by the TAB key, resulting in a basic HTML template. I don't know why, but typing the "!" character followed by a TAB key doesn't create the HTML template like it should.

Am I doing something wrong here? I know the package is installed correctly because typing something like "lorem" followed by the TAB key results in a paragraph of lorem ipsum, but for some reason or another the template shortcut doesn't work. This is one of those shortcuts that shaves off a buttload of gruntwork time, and i'd like to get this working correctly!

P.S. - For the record, the documentation has already been changed from plain text to HTML, so it's not a simple matter of picking the right syntax. Any suggestions?

substitute
Aug 30, 2003

you for my mum
Try ctrl/cmd + e, instead of tab.

luchadornado
Oct 7, 2004

A boombox is not a toy!

I thought I was finally up to speed on front end development, but I just found a ton of newer stuff this week that I'm not familiar with. Anyone care to chime in on their thoughts and usage of these two things?

1) Polymer/Web Components - Polymer seems like just some polyfills for compartmentalized stuff so you can easily re-use common ones, and you get the isolation that only iframes currently provide. These sound great, but browser support seems to be lacking and doesn't appear to be converging towards an accepted standard.

2) Function reactive programming/ClojureScript/Om/Rxjs/etc - Observables and Clojure and a bunch of things I don't understand at all. Why would you want to compile Clojure down to Javascript? Why is MVC horrible and reactive programming something more than hype?

piratepilates
Mar 28, 2004

So I will learn to live with it. Because I can live with it. I can live with it.



Helicity posted:

I thought I was finally up to speed on front end development, but I just found a ton of newer stuff this week that I'm not familiar with. Anyone care to chime in on their thoughts and usage of these two things?

1) Polymer/Web Components - Polymer seems like just some polyfills for compartmentalized stuff so you can easily re-use common ones, and you get the isolation that only iframes currently provide. These sound great, but browser support seems to be lacking and doesn't appear to be converging towards an accepted standard.


Yeah that seems about right. I'm not sure something like Polymer would really add that much in the future anyway since modern view libraries already work with everything in terms of small components. It's just that now they get thrown together in to one big mess, and when web components get wide support the same components will be nicely packed together and work the exact same.

quote:


2) Function reactive programming/ClojureScript/Om/Rxjs/etc - Observables and Clojure and a bunch of things I don't understand at all. Why would you want to compile Clojure down to Javascript?

People have a truly amazing capacity for hating javascript and refusing to work with it at all, which is why we now have things like Scala compiling to javascript, and Python compiling to javascript, and haskell compiling to javascript, and now a big push for C++ to javascript for some reason.

Now Clojure does seem like a good language and the ClojureScript community seems pretty good at providing a good environment (going mostly off of following David Nolen on twitter). Some people just like Clojure and would like to use that instead of javascript.

quote:


Why is MVC horrible and reactive programming something more than hype?

MVC probably isn't horrible. MVC itself is really just a name that has been applied to countless variations on the same concept of user interaction architectures over the years that all take the same general name but are slightly different.

The promise of reactive programming is to make codebases cleaner and easier to work with by reducing the amount of state and deep interactions. Instead everything is modeled as [input] -> stateless processing -> [output], with the inputs and outputs being things that listen to and publish on streams.

I think reactive is becoming noticed a lot more right now because people in general are turning away from old Java style OOP patterns to functional programming, and since javascript and UI in general so well suits reactive programming (since so much of the driver behind what web codebases do is events and waiting for events to happen and then setting off more events) that it's becoming a big storm of people wanting to try out reactive programming as much as possible.

Also React and Flux fueled that fire in a way since React suits immutability so well, and Flux is just an architecture that is nothing but events and suits immutability so well again.

Mellow_
Sep 13, 2010

:frog:

Helicity posted:

Our main solution has 87 projects

Jesus christ.

luchadornado
Oct 7, 2004

A boombox is not a toy!

AuxPriest posted:

Jesus christ.

We're a top 500 website that's part of an international media conglomerate and we have a lot of pages that do a lot of different things for a lot of different people. Our biggest concern is serving up news articles but there's lots more. Also, to be fair, some of those projects are cruft from before .NET MVC supported "areas" in a useful way.


Thanks for the good answers. I'll probably try to solve one of our common use cases in ClojureScript/Om or something and see what it gets me.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Videos from the ReactEurope conference will start being posted tonight here.

Also, I just wanted to highlight this amazing issue raised on the reddit issue tracker: https://github.com/reddit/reddit-mobile/issues/247

Thermopyle fucked around with this message at 19:37 on Jul 4, 2015

Kekekela
Oct 28, 2004

Thermopyle posted:

Videos from the ReactEurope conference will start being posted tonight here.

Excellent, I caught a few of the presentations on the live stream but at some point the audio got out of sync and I couldn't gut it out any further.

quote:

Also, I just wanted to highlight this amazing issue raised on the reddit issue tracker: https://github.com/reddit/reddit-mobile/issues/247

Haha, I was just reading this before checking the thread :fistbump:

piratepilates
Mar 28, 2004

So I will learn to live with it. Because I can live with it. I can live with it.



Does anyone know if there's a way in Babel or Webpack (or babel-loader for Webpack) to define imports in terms of a project root instead of having tons of '../../../fart/butt' import definitions everywhere?

I looked through the Babel options but nothing is too helpful since the promising ones only have one vague line telling you what it does.

Depressing Box
Jun 27, 2010

Half-price sideshow.

piratepilates posted:

Does anyone know if there's a way in Babel or Webpack (or babel-loader for Webpack) to define imports in terms of a project root instead of having tons of '../../../fart/butt' import definitions everywhere?

I looked through the Babel options but nothing is too helpful since the promising ones only have one vague line telling you what it does.

That sounds like resolve.modulesDirectories.

White Light
Dec 19, 2012

substitute posted:

Try ctrl/cmd + e, instead of tab.

Hrm, that's not doing anything either : (

This really is puzzling! It's bizarre, every other shortcut works just fine, it's only the "!" character that does nothing, both using TAB and with the above method.

White Light fucked around with this message at 18:09 on Jul 6, 2015

substitute
Aug 30, 2003

you for my mum

Parrotine posted:

Hrm, that's not doing anything either : (

This really is puzzling! It's bizarre, every other shortcut works just fine, it's only the "!" character that does nothing, both using TAB and with the above method.

Well I guess double-check the default Sublime shortcuts and the User shortcuts to see if there's an overlap.

gariig
Dec 31, 2004
Beaten into submission by my fiance
Pillbug
I need some Angular help because I don't know what I'm doing. A couple of developers started using Angular and I was tasked with fixing a bunch of the bugs. One page has a left hand side panel with a list of master-child items (say Foos with a list of Bars attached). When you click on a bar the UI on the right will show more information and the selection is saved in $scope.bar. There's an edit button, when clicked will show a modal edit form using an ng-click attribute that calls a showEditBar on the Controller passing vm.$scope.bar into it. The function sets a variable for the object being edited ($scope.barToEdit) and sets a boolean to show the modal edit window. Hit the save button which calls a function on the Controller (updateBar) and passes in barToEdit which calls Put on a Service that returns a Promise using $q to wrap the $http promise. Inside the Then I'm trying to set the data from the JSON API to $scope.bar, things aren't quite right. The slide out panel has the updated information but the list on the left hand side isn't updated. If I use angular.extend($scope.bar, data) that updates everything correctly.

I understand why angular.extend is working because the function is copying all of the data over, but I don't understand why direct assignment isn't. Is it because Angular doesn't know anything about the new object?

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me

gariig posted:

I need some Angular help because I don't know what I'm doing. A couple of developers started using Angular and I was tasked with fixing a bunch of the bugs. One page has a left hand side panel with a list of master-child items (say Foos with a list of Bars attached). When you click on a bar the UI on the right will show more information and the selection is saved in $scope.bar. There's an edit button, when clicked will show a modal edit form using an ng-click attribute that calls a showEditBar on the Controller passing vm.$scope.bar into it. The function sets a variable for the object being edited ($scope.barToEdit) and sets a boolean to show the modal edit window. Hit the save button which calls a function on the Controller (updateBar) and passes in barToEdit which calls Put on a Service that returns a Promise using $q to wrap the $http promise. Inside the Then I'm trying to set the data from the JSON API to $scope.bar, things aren't quite right. The slide out panel has the updated information but the list on the left hand side isn't updated. If I use angular.extend($scope.bar, data) that updates everything correctly.

I understand why angular.extend is working because the function is copying all of the data over, but I don't understand why direct assignment isn't. Is it because Angular doesn't know anything about the new object?

It's a little hard to follow what is going on from your description (as opposed to actual code or pseudo-code), but one thing to check is if the variable is not being set at ALL, or is just not being displayed. Put some console.logs in to show when it's updated and the new value, and see if the screen reflects it. If the variable is being updated, but not shown on the screen, it's an issue with your digest cycle.

Edit: To elaborate, angular.extend is probably working for different reasons than you think. If you are just setting bar.baz=1, and your $watch is set to bar, it won't notice that .baz has changed. When you use angular.extend, it is creating an entirely new object and assigning it to bar, which is what $watch is looking for (memory reference change on Objects, or value changes on primitive types).

This explains the different kinds of $watches and how they do(or don't) work.
http://teropa.info/blog/2014/01/26/the-three-watch-depths-of-angularjs.html

Skandranon fucked around with this message at 19:55 on Jul 7, 2015

gariig
Dec 31, 2004
Beaten into submission by my fiance
Pillbug
OK the different type of $watch is definitely what's getting me. Here is some of the code that is being used, I think this is everything that is needed. So the ng-repeat is using a Collection Watch but I'm modifying an individual item which it's not seeing on the master-detail listing side. The more details panel on the right is using a Reference Watch so that's why the angular.extend() is working.

As a dirty fix is attaching a By Value watch to $scope.Foos a valid fix? Should I try finding the Bar I editing in the array of Bars and replace with the new one? I don't think that would allow the slide out panel to update. I guess I could change both the Bars array and the BarToMod with the new item. Would that be the most Angular way to fix this?

Display of master-detail records
code:
<tr ng-repeat="d in vm.$scope.Foos | orderBy: sortBy:reverse | filter: searchSource">
    <th style="width: 10px"><div class="circle circle-green"></div></th>
    <td ng-class="{'active': vm.$scope.FooDetail == d}" style="font-weight: 700">{{d.name}}</td>

    <td>
        <ul style="list-style-type: none;">
            <li ng-repeat="s in d.Bars" style="margin-bottom: 10px">
                <div ng-click="vm.setBars(d,s)" ng-class="{'active': vm.$scope.Bar == s}" style="font-weight: 500">
                    {{s.name}}
                </div>                
            </li>
        </ul>
    </td>  
</tr>
This will setup the left hand side panel.
code:
setBar(dc: rm.FooItem, sn: rm.BarItem) {
    this.$scope.selection = 'Bar';
    this.$scope.dcDetail = dc;
    this.$scope.Bar = sn;    
}
Slide out panel
code:
<div ng-switch="vm.$scope.selection">
    <div id="col-right" ng-switch-when="Bar" class=" ">
        <div>
            <h2 class="pull-left">{{vm.$scope.Bar.name}}</h2>
            <div >
                <div style="margin: 15px 10px; width:75px" class="pull-right show-cursor  "
                ng-click="form.$setPristine(); form.$setUntouched(); vm.showEditBar(vm.$scope.Bar)">
                <i class="glyphicon glyphicon-cog" style="margin-left: 30px"></i>
                <div>Edit Bar</div>
                .......
            </div>
        </div>
    </div>
</div>
code:
showEditBar(sn: rm.BarItem) {
            this.$scope.BarToMod = angular.copy(sn);
            this.$scope.showSubnetForm = true;
        }
Code that saves using a service
code:
updateBar(Bar: rm.BarItem) {
    var self = this;
    this.$scope.successMessage = null;
    this.$scope.errorMessage = null;

    this.BarService.put(Bar).then(
        (data) => {
            var tempBar = new Models.BarItem(data);            
            self.$scope.Bar = tempBar;
            this.$scope.showBarForm = false;
            self.$scope.successMessage = "Successsfully updated Bar - " + Bar.name;
        },
        (error) => {
            self.$scope.addSubnetErrorMessage = error.data;
            window.scrollTo(0, 0);
        });
}

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me

gariig posted:

OK the different type of $watch is definitely what's getting me. Here is some of the code that is being used, I think this is everything that is needed. So the ng-repeat is using a Collection Watch but I'm modifying an individual item which it's not seeing on the master-detail listing side. The more details panel on the right is using a Reference Watch so that's why the angular.extend() is working.

As a dirty fix is attaching a By Value watch to $scope.Foos a valid fix? Should I try finding the Bar I editing in the array of Bars and replace with the new one? I don't think that would allow the slide out panel to update. I guess I could change both the Bars array and the BarToMod with the new item. Would that be the most Angular way to fix this?

Display of master-detail records
code:

Using a ByValue $watch is very expensive, not usually a good way to go. You also want to avoid creating completely new Bar objects, as this will force Angular to create/destroy whole new DOM elements which is probably not necessary. If I am reading your code right, your problem is not updating from within your this.BarService.put(Bar).then() promise. You could wrap that chunk of code in a $scope.apply(), which will make sure to call a $digest on $rootScope once the code contained within runs. This is preferable to using a Value watch, as the digest only happens after a specific change takes place, instead of the Value watch checking every field every $digest.

code:
(data) => {
            this.$scope.$apply(() => {
		var tempBar = new Models.BarItem(data);            
	        self.$scope.Bar = tempBar;
        	this.$scope.showBarForm = false;
	        self.$scope.successMessage = "Successsfully updated Bar - " + Bar.name;
            });
        }
Also, it looks like you are using TypeScript, I would suggest trying to use bindToController and controllerAs in your directives and avoid using $scope altogether. Your Controller classes will effectively store your variables & functions directly, making it a lot easier to manage them.

gariig
Dec 31, 2004
Beaten into submission by my fiance
Pillbug

Skandranon posted:

Using a ByValue $watch is very expensive, not usually a good way to go. You also want to avoid creating completely new Bar objects, as this will force Angular to create/destroy whole new DOM elements which is probably not necessary. If I am reading your code right, your problem is not updating from within your this.BarService.put(Bar).then() promise. You could wrap that chunk of code in a $scope.apply(), which will make sure to call a $digest on $rootScope once the code contained within runs. This is preferable to using a Value watch, as the digest only happens after a specific change takes place, instead of the Value watch checking every field every $digest.

code:
(data) => {
            this.$scope.$apply(() => {
		var tempBar = new Models.BarItem(data);            
	        self.$scope.Bar = tempBar;
        	this.$scope.showBarForm = false;
	        self.$scope.successMessage = "Successsfully updated Bar - " + Bar.name;
            });
        }
Also, it looks like you are using TypeScript, I would suggest trying to use bindToController and controllerAs in your directives and avoid using $scope altogether. Your Controller classes will effectively store your variables & functions directly, making it a lot easier to manage them.

OK I tried calling $scope.$apply() and now I'm getting

JS Error posted:

[$rootScope:inprog] $digest already in progress
with a stacktrace pointing to the the line of this.$scope.$apply. BTW, this is the service that is being called by put.
code:
put(Bar: rm.BarItem): ng.IPromise<rm.BarItem> {
    var self = this;
    var deferred = self.$q.defer();
    self.$http.put(self.BarsUrl, Bar)
    .then((result) => {
        deferred.resolve(result.data);
    },(error) => {
        deferred.reject(error);
    });

    return deferred.promise;
}
As far as the creating a BarItem is because the shape of data has Keys with C# naming (IE Name) instead of the JS naming. I don't know why the JSON serializer wasn't changed to make JSON with JS naming conventions. This isn't happening a lot because editing is not a very common occurrence. If I knew more Angular I bet this code could fit in the Coding Horrors thread.

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me
There doesn't seem to be anything wrong with that service call, though you could avoid using $q.defer altogether since $http.put() is already returning a promise. Also, what's with the var self=this? If you want a closure to be created for that method, just use => syntax for the function and TypeScript will handle the that=this pattern for you.

code:
put = (Bar: rm.BarItem): ng.IPromise<rm.BarItem> => {
    var deferred = this.$q.defer();
    this.$http.put(this.BarsUrl, Bar)
    .then((result) => {
        deferred.resolve(result.data);
    },(error) => {
        deferred.reject(error);
    });

    return deferred.promise;
}
The issue is that you shouldn't be calling $scope.apply() from within something already within another $scope.apply. Anything assigned to directives like ng-click and ng-change are wrapped by Angular in a $scope.apply. That's how Angular knows to show things have changed after clicking on things. These problems come from things Angular doesn't know about, like promises resolving from an API or push notifications or raw jQuery code. These need to be wrapped in $scope.apply(), but in such a way that they are not nested. Doing so doesn't actually cause anything to break, but Angular throws those errors to let you know that something is amiss.

I've seen worse ways to use Angular, so don't feel too badly about the state of the code base.

Edit: If you want to PM me more I can maybe help further, hard to track down digest issues with just fragments.

Skandranon fucked around with this message at 23:47 on Jul 7, 2015

an skeleton
Apr 23, 2012

scowls @ u
Thanks for the answer earlier, Skandranon. I typed out a longish reply to you but somehow it got lost in the Aether. Nonetheless, your advice was helpful.

I have another angular issue though -- I have a field (Angular UI Datepicker) that is always being marked as ng-invalid-required, in other words it is failing the required validation, gaining both "ng-invalid" and "ng-invalid-required" classes and messing up validation for the page, which involves submission being disabled if any field is invalid.

If I remove the ng-required attribute, the field validates just fine. All the other datepickers (there are a lot in the app), required or not, work fine, except a small subsection of them in this page.

HaB
Jan 5, 2001

What are the odds?

an skeleton posted:

Thanks for the answer earlier, Skandranon. I typed out a longish reply to you but somehow it got lost in the Aether. Nonetheless, your advice was helpful.

I have another angular issue though -- I have a field (Angular UI Datepicker) that is always being marked as ng-invalid-required, in other words it is failing the required validation, gaining both "ng-invalid" and "ng-invalid-required" classes and messing up validation for the page, which involves submission being disabled if any field is invalid.

If I remove the ng-required attribute, the field validates just fine. All the other datepickers (there are a lot in the app), required or not, work fine, except a small subsection of them in this page.

I'd start with dumping out field.value and field.$viewValue somewhere to see if anything looks funky. I've had weird validation problems on datepickers because of the wrong format being applied to the value, etc. So if value is like '07/04/2015' and $viewValue is showing like: '2015-07-04' then adjust. Try to use the ISO 8660 format whenever possible, then don't covert until you absolutely need to.

an skeleton
Apr 23, 2012

scowls @ u
I figured it out, though it still doesn't really make sense to me.

I have some $formatter code, that is parsing the date value.

code:
	if(tempMoment.isValid() && input){
                        tempMoment = tempMoment.format(config.correctFormat);
                    } else {
                        tempMoment = '';
                    }
It works now, but it didn't when it was this

code:
	if(tempMoment.isValid() && input !== undefined){
                        tempMoment = tempMoment.format(config.correctFormat);
                    } else {
                        tempMoment = '';
                    }
Because some empty inputs were defaulting to null or empty string, and they were therefore being defaulted into the view as moment(), aka today. For whatever reason this was messing up the ng-required validation.

my bony fealty
Oct 1, 2008

I've been asked by a coworker to take a look at an online application form our clients use that is rather user unfriendly and apparently has a high rate of abandonment before completion. It's written in vanilla JS and is spread across several pages. He wants me to mock up a more modern version that's easier to use and fully responsive. I was going to just make something simple with JS and a better design, but I want to try using one of the more modern frameworks. Since I'm doing this as a favor and not writing anything that will actually be deployed to the wild, I'm not worried about having production-quality code in the first version.

Any recommendations for the best tool here? I'm leaning towards Angular, as it seems to have robust form validation built in and two-way data binding seems enormously useful for forms.

White Light
Dec 19, 2012

You think you could write a program that could follow the lyrics of Rapper's Delight? I know you could use an if/else statement for part of the middle section:

if (girlActingUp) {currentSpeed--;} then {System.error.println("Take her friend")}

Something like that

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.

my bony fealty posted:

He wants me to mock up a more modern version that's easier to use and fully responsive. [...] I'm leaning towards Angular, as it seems to have robust form validation built in and two-way data binding seems enormously useful for forms.
Angular is fine, but with v2 on the horizon it might not be the best thing to pick up right now. It can also be a bit of a pain in the dick and not the most straight forward framework to work with.
Perhaps try out KnockoutJS. You can tack on PagerJS if you want to make it more of a client-side app with routing, rather than just a one-page tool.

I wouldn't say there's a "Best tool" in that sense, it's always tool-for-a-job. If you've got a few hours to waste, follows the starter tutorials for each (Angular, Knockout, React) and see what you think is most useful for your use case, and/or doesn't make you want to stab yourself.

Skandranon
Sep 6, 2008
fucking stupid, dont listen to me

my bony fealty posted:

I've been asked by a coworker to take a look at an online application form our clients use that is rather user unfriendly and apparently has a high rate of abandonment before completion. It's written in vanilla JS and is spread across several pages. He wants me to mock up a more modern version that's easier to use and fully responsive. I was going to just make something simple with JS and a better design, but I want to try using one of the more modern frameworks. Since I'm doing this as a favor and not writing anything that will actually be deployed to the wild, I'm not worried about having production-quality code in the first version.

Any recommendations for the best tool here? I'm leaning towards Angular, as it seems to have robust form validation built in and two-way data binding seems enormously useful for forms.

Simple forms applications are what Angular was really designed to handle. I wouldn't worry about Angular 2.0 coming out, it's still at least 6 months out, and the 1.x line will be supported for at least 2 years after 2.0 comes out. Also, if you use something like Typescript, you can do your Angular 1.x app in a way that makes transitioning easier.

kloa
Feb 14, 2007


I may need to hit up the JS thread, but would d3js be the easiest/fastest way to visually display backend data?

We typically use Tableau/ReportingServices with SQL Server/cubes, but I'd like to delve more into the webapp/front-end side and learn something new.

Adbot
ADBOT LOVES YOU

bartkusa
Sep 25, 2005

Air, Fire, Earth, Hope

kloa posted:

I may need to hit up the JS thread, but would d3js be the easiest/fastest way to visually display backend data?

We typically use Tableau/ReportingServices with SQL Server/cubes, but I'd like to delve more into the webapp/front-end side and learn something new.

The "fastest" way to "visually display" backend data is to dump the data as an HTML table to the browser; no JS needed.

What kind of data do you have, and what do you want to visualize about it?

If you just want to do bar/line graphs, D3 is too low-level.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply